Antecedents feed

In the last video, Light’s hot and dry noodle shop has started serving drinks with it. With the help of a beautiful cousin, business is booming.

However, things are not perfect, slowly xiaoguang heard some of the customer’s voice: plum soup is too sour, can you tune a little better? It’s getting cold. Can I get you something hot?

Customer is god, light immediately began to improve.

Cousin’s Complaint

With the voice of the customer, xiao Guang talked to her cousin, want to let her cousin modify the current plum soup bubble proportion, in addition to add some hot drinks.

To my surprise, when her cousin heard this, she objected: “I have already remembered too much now, and it will be easier for me to remember and mix it up, and then there will be more problems.”

Yes, I freed myself from the worry of making hot dry noodles and adding ingredients (in Builder mode). I can’t put my cousin through that.

The road to solve

But how can we solve this problem better? If only I had many Cousins, each responsible for a drink, thought light. HMM, lots of Cousins? ! Small light smiles slightly, plan on heart.

Light bought a number of mini water fountains, each containing a drink, and labeled them accordingly, and so on:

Each mini water dispenser acts as a drink machine and is used to produce different drinks. Cousin only according to the needs of users to choose different beverage machine drinks can be.

In this way, my cousin does not need to pay attention to the production process of the drink, and does not need to remember so many beverage configuration methods. If you want to add new drinks, you just need a drink machine.

Let’s look at the correspondence

Here’s the water dispenser without the label:

public interface IBeverageMachine {

    Drink makeDrink(a);
}Copy the code

Here’s a drink machine with different types of drinks:

public class OrangeJuiceMachine implements IBeverageMachine {
    @Override
    public Drink makeDrink(a) {
        return newOrangeJuice().make(); }}public class CokeMachine implements IBeverageMachine {
    @Override
    public Drink makeDrink(a) {
        return newCoke().make(); }}public class PlumJuiceMachine implements IBeverageMachine {
    @Override
    public Drink makeDrink(a) {
        return newPlumJuice().make(); }}Copy the code

Here are those drinks (again with an abstract inheritance):

public abstract class Drink {

    private String name;
    private String instantPackage;

    public Drink make(a) {
        this.name = getName();
        this.instantPackage = getInstantPackage();
        return this;
    }

    abstract String getInstantPackage(a);
    abstract String getName(a);

    @Override
    public String toString(a) {
        return "This is a cup of:" + this.name; }}public class Coke extends Drink {
    @Override
    String getInstantPackage(a) {
        return "Instant Coke powder";
    }

    @Override
    String getName(a) {
        return "Coke"; }}public class OrangeJuice extends Drink {
    @Override
    String getInstantPackage(a) {
        return "Instant orange juice powder";
    }

    @Override
    String getName(a) {
        return "Orange juice"; }}public class PlumJuice extends Drink {
    @Override
    String getInstantPackage(a) {
        return "Instant sour plum powder";
    }

    @Override
    String getName(a) {
        return "Plum soup"; }}Copy the code

In contrast to the previous simple factory drinks article, we removed packaging from the drinks object, which is now just a few simple properties. Why do you do that? You can use your own object-oriented programming imagination, and I’ll tell you what I think next time.

Now the cousin’s job is easy:

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(newCokeMachine()); System.out.println(cousins.takeDrink()); }}Copy the code

When A asked for orange juice, cousin went to OrangeJuiceMachine to fill A cup. When B needed coke, cousin went to CokeMachine to get it:

This is a cup of orange juiceCopy the code

Cousin’s work has become easier, work efficiency is also higher, also can smile in the face of customers, ha ha…

Customer C who wants milk tea

One day, a customer D came and asked: “Boss, do you have hot milk tea?” .Time to test little Light’s program. Soon, the light copy out of a milk tea machine (expanded open), at the same time, there is no need to modify the original beverage machine program (modified closed), so it will not delay business.

New milk tea beverage:

public class MilkTea extends Drink {
    @Override
    String getInstantPackage(a) {
        return "Instant milk Tea Powder";
    }

    @Override
    String getName(a) {
        return "Milk tea"; }}Copy the code

Milk tea machine:

public class MilkTeaMachine implements IBeverageMachine {
    @Override
    public Drink makeDrink(a) {
        return newMilkTea().make(); }}Copy the code

Table now:

My cousin’s job is also very simple, just go to the machine to pick up milk tea:

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

D:

This is a cup of milk teaCopy the code

After the story

As usual, we first draw the correspondence between the classes that appear:

This is actually the factory method pattern.

A few points: 1, the factory method is called because each factory has a method to create a product; 2, each product has a factory instance to produce the product instance; 3, because the product and its corresponding factory are separated from other products, we can easily add new products and its corresponding factory. (The open and closed principle, in fact, also implies a single responsibility)

Further reading

The factory method pattern, like the Buidler pattern, is a very common design pattern used to create instances in some open source libraries.

For example, the implementation of ModelLoader in OkHttp:

Look at the correspondence with clear, not an analogy.

Looking at this row of beverage machines, Xiao Guang felt a sense of accomplishment, as if he had gone back to the coding days all night.