Head First设计模式-模板方法

设计模式的代码仓库:
设计模式

在这里插入图片描述
适用环境:
i. 一次性实现一个算法的不变的部分,并将可变的行为留给子类来实现。
ii. 各子类中公共的行为应被提取出来并集中到一个公共父类中以避免代码重复。
iii. 对一些复杂的算法进行分割,将其算法中固定不变的部分设计为模板方法和父类具体方法,而一些可以改变的细节由其子类来实现。
iv. 控制子类的扩展。

好莱坞原则:
Don’t call me, we’ll call you.

进一步3:策略模式与模板方法模式比较
策略模式和模板方法模式很像,都是针对算法改变的情况的设计模式。

我们对比下两者的定义:
策略模式定义了算法族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。
模板方法模式在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。

很明显可以看出:
策略模式是采用的组合来实现算法的变化,这样的设计更加灵活,依赖性程度低;
模板方法模式采用的继承来实现算法中的变化部分,这样的设计对算法有更多的控制权,且代码的重复会少一些,但由于算法依赖于父类,所以依赖程度高。

/**
 * 咖啡因饮料
 */
public abstract class CaffeineBeverage {
    /**
     * 模板方法,准备饮料
     */
    public final void prepareRecipe(){
        boilWater();
        brew();
        //用于模板方法的算法中可选部分的控制
        if(customerWantsCondiment()){
            addCondiment();
        }
        pourInCup();
    }

    /**
     *  煮沸水
     */
    public void boilWater() {
        System.out.println("煮沸水");
    }

    /**
     *  冲泡
     */
    public abstract void brew();

    /**
     *  增加调味剂
     */
    public abstract void addCondiment();

    /**
     * 将饮料倒入杯子
     */
    public void pourInCup() {
        System.out.println("将饮料倒入杯中");
    }

    /**
     * “钩子”方法。顾客决定是否加调料
     */
    public Boolean customerWantsCondiment(){
        return true;
    }
}
public class Coffee extends CaffeineBeverage{

    @Override
    public void brew() {
        System.out.println("冲泡咖啡粉");
    }

    @Override
    public void addCondiment() {
        System.out.println("添加糖和牛奶");
    }

}
public class Tea extends CaffeineBeverage{

    @Override
    public void brew() {
        System.out.println("浸泡茶叶");
    }

    @Override
    public void addCondiment() {
        System.out.println("添加蜂蜜");
    }
}

hook写法

public class Tea extends CaffeineBeverage {

    @Override
    public void brew() {
        System.out.println("浸泡茶叶");
    }

    @Override
    public void addCondiment() {
        System.out.println("添加蜂蜜");
    }

    //覆盖父类的“钩子”方法,更改算法中的可选部分
    @Override
    public Boolean customerWantsCondiment(){
        //询问顾客是否需要调料
        String answer = askCustomerNeedCondiment();
        if("y".equals(answer))
            return true;
        else
            return false;
    }

    private String askCustomerNeedCondiment() {
        String answer = null;

        System.out.println("请问您要不要加蜂蜜?请回答y或n");
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        try {
            answer = in.readLine();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return answer;
    }
}
已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 酷酷鲨 设计师:CSDN官方博客 返回首页