Strategy Pattern

Definition

This pattern defines a family of algorithms,  encapsulates each one and make them interchangeable.

Strategy lets the algorithm vary independently from clients that use it.

image

Figure  01. Class diagram Ref: http://en.wikipedia.org/wiki/Strategy_pattern

Scenario

We need to design a Customer Promotion Tool for a cell phone company, on which per different seasons of the year or any special random day that the manager of the company came up in his mind, there is supposed to be a new promotion notified to the  customer when he wants to buy a new telephone so he/she can have a discount on his/her buying and by that way be happier 😀

Class Diagram

For the scenario described we have the following class diagram:

UntitledDocument (1)

Figure 02. Class diagram of the case of study.

The strategy pattern was applied on the calculation of the promotional prices as is shown in the previous figure. For this example the Context is the Calculator class and the Strategy is the Promotion interface.

To get an idea of the way that the pattern was implemented, this is the class that will do the product calculations:

ProductCalculator.class

package chris.desingpatterns.strategy.calculations;

import chris.desingpatterns.strategy.products.Product;
import chris.desingpatterns.strategy.promotions.Promotion;

public class ProductCalculator implements Calculator {
    private Product product;
    private Promotion promotion;

    public ProductCalculator(Product product) {
        this.product = product;
    }

    /**
     * {@inheritDoc}
     */
    public float getCalculation() {
        float productPrice = product.getProductPrice();
        float calculatedPrice = productPrice;

        if(promotion != null){
            float discount = promotion.getPromotionDisscount(productPrice);
            calculatedPrice -= discount;     
        }

        return calculatedPrice;
    }

    public Promotion getPromotion() {
        return promotion;
    }
    public void setPromotion(Promotion promotion) {
        this.promotion = promotion;
    }
    public Product getProduct() {
        return product;
    }
    public void setProduct(Product product) {
        this.product = product;
    }
}

And this is one of the implementations of the Promotions:

WinterPromotion.class

package chris.desingpatterns.strategy.promotions;

public class WinterPromotion implements Promotion {

    public String getPromotionName() {
        return "Winter Promotion";
    }

    public float getPromotionDisscount(float originalPrice) {
        return originalPrice * 30/100;
    }

    public String getPromotionInformation() {
        return "This is the Witer Promotion, because the weather " +
                "is cold and you are spending all your money paying " +
                "the gas bills, buy one of our products" +
                "and get an amazing discount of 30%";
    }

}

And finally the class that will run the case of study for this design pattern:

Main.class

package chris.desingpatterns.strategy;

import chris.desingpatterns.strategy.calculations.Calculator;
import chris.desingpatterns.strategy.calculations.ProductCalculator;
import chris.desingpatterns.strategy.customer.Customer;
import chris.desingpatterns.strategy.products.Htc;
import chris.desingpatterns.strategy.products.Product;
import chris.desingpatterns.strategy.promotions.BirthdayPromotion;
import chris.desingpatterns.strategy.promotions.Promotion;
import chris.desingpatterns.strategy.promotions.SummerPromotion;
import chris.desingpatterns.strategy.promotions.WinterPromotion;

public class Main {
    public static void main(String[] args) {
        Customer kasia = new Customer("Kasia");

        Product htcPhone = new Htc();
        kasia.buyProduct(htcPhone);

        // Case 01 Summer Promotion
        Promotion summerPromotion = new SummerPromotion();
        Calculator calculator = new ProductCalculator(htcPhone);
        calculator.setPromotion(summerPromotion);
        System.out.println(".:. Case 1: ");
        printInfo(kasia, htcPhone, calculator, summerPromotion);

        // Case 02 Winter Promotion
        Promotion winterPromotion = new WinterPromotion();
        calculator.setPromotion(winterPromotion);
        System.out.println(".:. Case 2");
        printInfo(kasia, htcPhone, calculator, winterPromotion);

        // Case 03 Birthday Promotion
        Promotion bdayPromotion = new BirthdayPromotion();
        calculator.setPromotion(bdayPromotion);
        System.out.println(".:. Case 3");
        printInfo(kasia, htcPhone, calculator, bdayPromotion);

    }

    private static void printInfo(Customer customer, Product product,
            Calculator calculator, Promotion promotion) {

        System.out.println("Hi " + customer.getName() + "!");
        System.out.println(promotion.getPromotionInformation());

        System.out.println("The original price of the: "
                + product.getProductName() + " is: "
                + product.getProductPrice() + "Euros");

        System.out.println("The price of your " + product.getProductName()
                + " thanks to the promotion: " + promotion.getPromotionName()
                + " will be: " + calculator.getCalculation() + "Euros");

        System.out.println("-----------------------------");
    }

}

As we can see, applying the Strategy Pattern makes the design more flexible in case a new promotion needs to be introduced, removed or simply updated, and the most important thing is that all these changes will not affect the way that the class ProductCalculator works. Modifications of promotions are done only under the Promotion classes.

If you want to check all the implementation of the case of study, download the code here:

Strategy Pattern Code

Do you have any recommendations or amendments to be done, please let me know to improve this post!