设计模式学习笔记--模板方法模式

1.设计原则
好莱坞原则:底层组件可以挂钩到我们自己的系统上,由高层组件决定合适调用以及如何使用低层组件,但是低层组件绝对不可以去直接调用高层组件
 
2.学习笔记
    · 模板方法模式:模板方法定义了一个算法的步骤,抽离出相同的操作,并允许子类为一个或多个步骤提供具体实现
    · 钩子(hook):被声明在抽象类中的方法,只有空的活着默认的实现,子类可以根据实际情况决定是否要进行覆盖钩子(hook)方法
    · 钩子(hook)使用的真正目的:
        1. 可以让子类实现算法中可选部分
        2. 可以让子类能够有机会对模板中某些即将发生(或刚刚发生)的步骤作出反应   
    · 工厂方法是模板方法的一个特殊版本
 
3.代码实践——以烧菜为例
 
    · 1. 实现一个抽象类,实现共有的方法,并将子类需要实现的方法分离为抽象方法
 
package headFirst.templateDesignPattern;


/**
 * @author kaithy.xu
 * @date 2019/4/14 14:13
 */
public abstract class FoodCook {

    //模版方法,定义为final,防止子类覆盖
    final void prepareDinner(){
        prepareFood();
        powerOn();
        cookMethod();
        addCondiments();
        pourInPlate();
        if (hook()){
            annouceDinnerIsReady();
        }
    }

    //抽象方法,准备食物
    abstract void prepareFood();

    //抽象方法,选择烹饪方式
    abstract void cookMethod();

    //抽象方法,选择添加的配料
    abstract void addCondiments();

    //公共方法在抽象类中实现,子类可以自己选择是否覆盖
    void powerOn(){
        System.out.println("the induction cooker is electrified");
    }

    //公共方法
    void pourInPlate(){
        System.out.println("the food is cooked and is poured in plate");
    }
    void annouceDinnerIsReady(){
        System.out.println("tell everyone dinner is ready");
    }
    //默认hook方法,当子类不覆盖此方法时,模板中使用此方法
    boolean hook(){
        return false;
    }
}

 

·2. 子类继承此抽象类,并实现抽象方法,实现子类自己独有的方法
 
package headFirst.templateDesignPattern;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

/**
 * @author kaithy.xu
 * @date 2019/4/14 14:24
 */
public class CookFish extends FoodCook {

    @Override
    void prepareFood() {
        System.out.println("scale and gut fish");
    }

    @Override
    void cookMethod() {
        System.out.println("braise fish in brown sauce");

    }

    @Override
    void addCondiments() {
        System.out.println("add shallot, ginger and garlic");
    }
    //子类实现hook方法,通过用户输入以决定模板方法的走向
    @Override
    boolean hook() {
        String answer = null;
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));

        while (true){
            System.out.println("is dinner ready ? (y/n)");

            try {
                answer = in.readLine();
            }catch (IOException e){
                System.out.println("IO error trying to read your answer");
            }

            if(answer == null || answer.equalsIgnoreCase("n")){
                return false;
            }else if(answer.equalsIgnoreCase("y")){
                return true;
            }else {
                System.out.println("wrong input,please input again \n");
            }
        }

    }
}

 

package headFirst.templateDesignPattern;

/**
 * @author kaithy.xu
 * @date 2019/4/14 14:31
 */
public class CookDrumstick extends FoodCook {

    @Override
    void prepareFood() {
        System.out.println("wash the drumsticks with boiled water, widen the opening with knife");
    }

    @Override
    void cookMethod() {
        System.out.println("deep fry the drumsticks and pour the coca cola after the color of drumsticks turn into golden ");

    }

    @Override
    void addCondiments() {

        System.out.println("add rock candy , yellow rice wine and light soy sauce and dark soy sauce");
    }
}

 

 
·3. 用户调用
 
package headFirst.templateDesignPattern;

/**
 * @author kaithy.xu
 * @date 2019/4/14 15:06
 */
public class Client {

    public static void main(String[] args){

        CookDrumstick drumstick = new CookDrumstick();

        drumstick.prepareDinner();

        CookFish fish = new CookFish();

        fish.prepareDinner();
    }
}
 
4.类结构图
 
    · 范例代码类结构图
 
    ·模板方法UML图:
 
 
抽象类中含有模板方法,模板方法在实现算法的过程中,使用了primitiveOperation1() 和 primitiveOperation2()这两个原语操作,模板本身和这两个操作的具体实现之间被解耦了,在子类中,需要要实现模板所必需的原语操作,这样当模板需要使用原语操作的时候,会到子类中去调用
 
posted @ 2019-04-15 20:38  奶昔书斋  阅读(37)  评论(0)    收藏  举报