Antecedents feed

In the last video, Light introduced the beverage machine (factory method model) to improve the production process of Light’s drinks. Now, if you want to add a new drink, change the recipe or whatever, it’s as simple as adding a drink machine or replacing/removing a drink machine. My cousin didn’t complain any more.

Light also found some beverage manufacturers and got some new drinks to sample. I thought, as Thanksgiving, Christmas and Double 12 were approaching, I could do some activities with these new drinks to express my gratitude to new and old customers. These new light but personally tried to drink, absolutely good to drink, light do not do profiteer, 🙂

All sample source code has been uploaded to Github, poke here

Event planning

Light with its unique code farmer business thinking (I don’t know what this is…) , quickly came up with several activity plans:

  • From now on, until Thanksgiving Day (11/24), all drinks are 60% off.
  • On the day of the double 12, 2 yuan will be deducted immediately.
  • From December 20 to Christmas (12/25), buy hot and dry noodle + drink package and get big Apple.

Light came up with these activities, pidianpidianpidian to show her cousin. I never thought, my cousin looked so unhappy, so many plans, but also so responsible, how can I remember… (unicellular cousin).

How to do, light can not want to give up their very not easy to come up with these plans, and activities will certainly be different because of the festival and change.

The solution

Soon, Light came up with a solution, he will do three activities of the algorithm, built in the cashier desk. Choose different algorithm strategies on different days.

“I am a genius, ha ha ha ha,” thought Light, almost laughing out loud…

As usual, the cashier does not care about the specific algorithm, so abstracts a parent interface:

public interface ActivityStrategy {

    String getActivityPrice(a);
}Copy the code

Each scheme corresponds to an algorithm strategy:

// Thanksgiving activity algorithm
public class ThanksGivingDayStrategy implements ActivityStrategy {

    @Override
    public String getActivityPrice(a) {
        // Through a series of algorithms
        return "50% off all drinks."; }}// Double twelve algorithm
public class DoubleTwelveDayStrategy implements ActivityStrategy {

    @Override
    public String getActivityPrice(a) {
        // Through a series of algorithms
        return "(Double 12) immediately minus 2 yuan after 12."; }}// Christmas algorithm
public class ChristmasStrategy implements ActivityStrategy {

    @Override
    public String getActivityPrice(a) {
        // Through a series of algorithms
        return "(Christmas) buy hot and dry noodles + drink set, get a big apple"; }}// Default algorithm (note this, the meaning of the Default implementation will be explained later in the extended reading)
public class DefaultActivityStrategy implements ActivityStrategy {
    @Override
    public String getActivityPrice(a) {
        // Do nothing
        return "No activity"; }}Copy the code

Cash registers that support various activity strategy algorithms:

/ / cashier
public class Checkstand {

    private ActivityStrategy mActivityStrategy;

    public Checkstand(a) {
        mActivityStrategy = new DefaultActivityStrategy();
    }

    public Checkstand(ActivityStrategy activityStrategy) {
        this.mActivityStrategy = activityStrategy;
    }

    public void setActivityStrategy(ActivityStrategy activityStrategy) {
        this.mActivityStrategy = activityStrategy;
    }

    public void printBill(a) {
        System.out.println("This billing activity :"+ mActivityStrategy.getActivityPrice()); }}Copy the code

Put into use

After the completion of the activity scheme algorithm and the cashier desk, the light was immediately put into use:

public class XiaoGuang {

    public static void main(String[] args) {

        // Register, default
        Checkstand checkstand = new Checkstand();
        checkstand.printBill();

        // During Thanksgiving
        checkstand.setActivityStrategy(new ThanksGivingDayStrategy());
        checkstand.printBill();

        / / 12-12
        checkstand.setActivityStrategy(new DoubleTwelveDayStrategy());
        checkstand.printBill();

        // During Christmas
        checkstand.setActivityStrategy(newChristmasStrategy()); checkstand.printBill(); }}Copy the code

The result, too, was as Little Light had predicted:

Check event: No check event :(Thanksgiving) All drinks will be served5Discount this bill activity :(double 12) full12knock2Yuan this bill activity :(Christmas) buy hot and dry noodles + drinks set, give a big appleCopy the code

As soon as the event was launched, there were more customers than ever before… People are also full of praise for the new sample drinks, they all feel good taste, but also a very interesting name…

After the story

As usual, after the story, we use UML class diagram to sort out the above relationship (focusing on the relationship between the cash register and the activity strategy algorithm):

You can probably see that already, yes, that’s the strategic pattern.

Strategy Pattern: Define a set of algorithms and encapsulate each individual algorithm so that they are interchangeable.

Strategy mode let the algorithm independent of the use of its customers and change, for example, if next year’s double Twelve activities changed, just modify the DoubleTwelveDayStrategy alone, customer class (Checkstand) need not change, do not need to pay attention to the specific implementation of each algorithm.

Extended Reading 1

In fact, the strategy pattern also uses abstraction, encapsulation, inheritance, polymorphic object-oriented characteristics to achieve encapsulation change, decoupling. Typical practice of the open close principle.

On the other hand, if you’re sharp-eyed, you might notice that this class diagram looks familiar. The class diagram in the simple factory and factory methods described earlier looks very similar:

Comparing the three patterns in the red box above, we can see that they are quite consistent. Make clear the relationship and difference among the three:

  1. First, simple factories and factory methods are creative patterns, while policy patterns are behavioral patterns.
  2. The so-called creation mode is used to produce objects, focusing on the production (new) part, using the creation mode instead of directly new an instance, more is to convert the direct instance dependency through different methods interface dependency.
  3. Behavioral patterns are more about the relationship between A behavior and how B uses it.

In fact, we already used the strategic pattern in the last factory method story.

Cousin chooses different beverage machines to drink, which is actually a reflection of strategic mode. Let’s review the code of Cousin:

public class Cousins {

    private IBeverageMachine mBeverageMachine;

    private void setBeverageMachine(IBeverageMachine machine) {
        this.mBeverageMachine = machine;
    }

    private Drink takeDrink(a) {
        if (mBeverageMachine == null) throw new NullPointerException("Should set Beverage Machine firstly.");

        return mBeverageMachine.makeDrink();
    }

    public static void main(String[] args) {

        Cousins cousins = new Cousins();

        // for A
        cousins.setBeverageMachine(new OrangeJuiceMachine());
        Drink drink = cousins.takeDrink();
        System.out.println(drink);

        // for B
        cousins.setBeverageMachine(new CokeMachine());
        System.out.println(cousins.takeDrink());

        // for D
        cousins.setBeverageMachine(newMilkTeaMachine()); System.out.println(cousins.takeDrink()); }}Copy the code

It is the same as our Checkstand. The mode in the above example can be actually understood as follows:

  • The blue part is the use of the factory method model, which is used to produce different drinks.
  • The red part is the use of strategy mode, the role is to let the cousin choose different beverage machine according to the actual situation.

Therefore, the application of patterns is often not simple and single, but often a combination of many patterns.

Extended Reading 2

The DefaultActivityStrategy class is marked red in the UML class diagram showing the strategy pattern in this example. Why?

This is because the DefaultActivityStrategy we use here is actually a reflection of the design mode. This pattern is not included in GoF’s 23 design patterns, but it is definitely a very common and useful pattern – the empty object pattern.

Null Object Pattern: Replace Null with an empty (do nothing) Object.

The empty object pattern is a very simple design pattern that can also be viewed as a coding habit. It is small but powerful:

  • Using the empty object pattern can reduce a lot of our judgment about whether objects are empty or not. For example, if the Checkstand no-argument constructor does not have a new empty object, then subsequent calls to the Checkstand instance may need to determine whether its mActivityStrategy is empty. If omitted, a NULL pointer exception is likely to result.
  • In addition, for some objects that can be called chained, if we have to check whether or not it is empty every time, it will affect our chained calls.

The empty object pattern is often used as part of a family of policy pattern algorithms to provide empty policies.

Extension Reading 3

Because of its excellent external scalability and internal encapsulation, policy pattern is often used in some SDK or excellent open source libraries. Glide, for example, uses policy mode for its image disk cache and provides a number of policies for users to choose from:

Good source code is always cleverly designed but understandable.

Activity up, small light hot dry noodles welcome you often come to visit ah, like you collect, like you pay attention to…