Template Method design pattern (b)

Previous We have learned a template method pattern, this time we continue to come under further study. After all, we learned only the first step, and further in-depth study and waiting for us.

We first look at the class diagram a summary of the template method pattern:

Let's take a closer look abstract class is how they are defined, including the template method it contains and primitive operations.

abstract class AbstractClass {
// 这就是模板方法。它被声明为final,以免子类改变这个算法的顺序
    final void templateMethod() {
    // 模板方法定义了一连串的步骤,每个步骤由一个方法代表
        primitiveOperation1();
        primitiveOperation2();
        concreteOperation();
        hook();
    }
    
    abstract void primitiveOperation1();
    
    abstract void primitiveOperation2();
    
    final void concreteOperation() {
        // 这里是实现
    }
    
    // 这是一个具体的方法,但他什么都不做。我们叫它为hook(钩子),马上就来揭晓它如何使用
    void hook();
}

Be linked to the template method

Hook is a method declared in an abstract class, but only empty or default implementation. There is a hook, allowing subclasses has the ability to be linked to different points of the algorithm. To not linked to the subclass.

Hook has many uses, we look at one:

public abstract class CaffeineBeverageWithHook {
 
    final void prepareRecipe() {
        boilWater();
        brew();
        pourInCup();
        // 我们加上一个小小的条件语句,该条件是否成立,是由一个具体方法决定
        if (customerWantsCondiments()) {
            addCondiments();
        }
    }
 
    abstract void brew();
 
    abstract void addCondiments();
 
    void boilWater() {
        System.out.println("Boiling water");
    }
 
    void pourInCup() {
        System.out.println("Pouring into cup");
    }
 
    // 这就是一个钩子,子类可以覆盖这个方法,但不一定需要使用
    boolean customerWantsCondiments() {
        return true;
    }
}

In order to use the hook, we cover it in a subclass. Here, a hook control part of the algorithm whether caffeine beverages; for example, the need to drink added spices

public class CoffeeWithHook extends CaffeineBeverageWithHook {
 
    public void brew() {
        System.out.println("Dripping Coffee through filter");
    }
 
    public void addCondiments() {
        System.out.println("Adding Sugar and Milk");
    }
 
    public boolean customerWantsCondiments() {
        // 询问用户,是否要加调料
        String answer = getUserInput();

        if (answer.toLowerCase().startsWith("y")) {
            return true;
        } else {
            return false;
        }
    }
 
    private String getUserInput() {
        String answer = null;

        System.out.print("Would you like milk and sugar with your coffee (y/n)? ");

        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        try {
            answer = in.readLine();
        } catch (IOException ioe) {
            System.err.println("IO error trying to read your answer");
        }
        if (answer == null) {
            return "no";
        }
        return answer;
    }
}

Above is a hook, ask if the customer wants spices? If necessary, on the implementation of contents, or not implemented. Test code is as follows:

public class BeverageTestDrive {
    public static void main(String[] args) {
 
        Tea tea = new Tea();
        Coffee coffee = new Coffee();
 
        System.out.println("\nMaking tea...");
        tea.prepareRecipe();
 
        System.out.println("\nMaking coffee...");
        coffee.prepareRecipe();

 
        TeaWithHook teaHook = new TeaWithHook();
        CoffeeWithHook coffeeHook = new CoffeeWithHook();
 
        System.out.println("\nMaking tea...");
        teaHook.prepareRecipe();
 
        System.out.println("\nMaking coffee...");
        coffeeHook.prepareRecipe();
    }
}

The results are as follows: tea with spices give you added; coffee does not need to add spices, did not give you extra

Making tea...
Boiling water
Steeping the tea
Pouring into cup
Would you like lemon with your tea (y/n)? y
Adding Lemon

Making coffee...
Boiling water
Dripping Coffee through filter
Pouring into cup
Would you like milk and sugar with your coffee (y/n)? n

So, what we use the hook real purpose is it?

Hook has several uses. As we said before, so that subclasses can hook an optional part of the algorithm, or the hook is not important for achieving sub-class, sub-class can ignore this hook. Another use of the hook is to allow subclasses have the opportunity to respond to some of the template method (or just happened) step imminent. For example, a method named hook justReOrderedList () allow subclasses to perform certain actions in the reorganized internal list (e.g., data re-displayed on the screen). As you have just seen, the hook also allows subclasses have the ability to make decisions for their abstract class.

Hollywood principle

Hollywood principle : Do not call (call) us, we will call (call) you.

Hollywood principle method "relies corruption" gives us a prevent. When the high-level components rely on low-level components, while low-level components are also dependent high-level components, and high-level components are also dependent side components and side components are also dependent low-level components, rely corruption occurs. In this case, no one can easily get to know how the system design.

In Hollywood principle, we allow low-level components to hook themselves onto the system, but the high-level assembly will decide when and how to use these low-level components. In other words, high-level components to treat low-level components of the approach is "Do not call us, we'll call you."

The connection between Hollywood and the principles template method is actually fairly obvious: When we design template method, we tell subclass "Do not call us, we'll call you." How can we do it? Let's take a look at caffeine's design:

We also know that a principle called Dependency Inversion principle, the principle of Hollywood is a little taste of this right before. The relationship between them is how to do?

Dependency Inversion Principle teaches us to avoid the use of specific classes, and multi-utility abstraction. The Hollywood principle is a technique used in the creation of the frame or component, so that low-level components can be hooked into the calculations, but do not make high-level components rely on low-level components. Both goals that are decoupled, but since the inversion principle pay more attention to how to avoid relying on the design.

Hollywood principles we teach a skill, to create a flexible design that allows low-level structure can operate with each other, while preventing other classes too dependent on them.

So we put the said opening hidden principle to introduce over, also know further use template method pattern hook, let us in actual combat can have a better choice. This design mode, you get to it?

In this small series had wanted to end, but looked at the book and found that there is a closer behind the actual unexpected template method, but we usually use to, we next come to talk.

Love life, love of learning and perception, kicked love

Guess you like

Origin www.cnblogs.com/dimple91/p/10959204.html