Java设计模式——模板方法模式

Java设计模式之模板方法模式

模板方法:定义了一个算法的步骤,并允许子类为一个或多个步骤提供实现。

模板方法使得子类在可以不改变算法结构的情况下,重新定义算法的某些步骤。

这个模式用来定义一个模板方法,这个方法将总的算法定义成多个步骤,其中步骤可以是抽象的,由子类负责实现;其中不变的步骤(共有的)由该抽象类本身实现。(和策略模式很像,但是策略模式使用组合,更加解耦)

方法分为三种

  1. 抽象方法:一个抽象方法由抽象类声明、由其具体子类实现。
  2. 具体方法:一个具体方法由一个抽象类或具体类声明并实现。
  3. 钩子方法:一个钩子方法由一个抽象类或具体类声明并实现,而其子类可能会加以扩展。通常在父类中给出的实现是一个空实现,并以该空实现作为方法的默认实现,当然钩子方法也可以提供一个非空的默认实现。

钩子

钩子方法是指步骤中可选的部分,可以使用钩子为某些步骤做判断是否要执行

挂钩

与某些步骤有关系(挂钩)的钩子方法。

//这个wantCondiments就是一个挂钩
if(wantCondiments()) {
            addCondiments();
        }

Head first 设计模式案例

饮料类的生产步骤:

  1. 烧水
  2. 冲泡
  3. 等待
  4. 加原料

其中24是抽象方法,不同饮料有不同的实现,13是不变的,具体的实现,由抽象类完成;判断用户是否需要加原料就是一个钩子hook。

public abstract class Drinks {
    /**
     * 这就是模板方法 里面调用了相关的算法(自己实现的和抽象的由子类实现的)
     */
    final void prepareDrinks(){
        //烧水
        boilWater();
        //冲泡
        pourCup();
        //等待
        waitForWhile();
        //添加原料
        //wantCondiments是挂钩
        if(wantCondiments()) {
            addCondiments();
        }
    }
    protected boolean wantCondiments() {
        return true;
    }
    private void boilWater(){
        System.out.println("步骤一:正在烧水");
    }
    protected abstract void pourCup();
    protected abstract void addCondiments();
    private void waitForWhile(){
        System.out.println("步骤三:等待5分钟");
    }
}
  • 咖啡
public class CoffeeDrinks extends Drinks{
    protected void pourCup() {
        System.out.println("步骤二:倒入咖啡粉冲泡");
    }
    protected void addCondiments() {
        System.out.println("步骤四:添加牛奶、摩卡和奶泡");
    }
    @Override
    protected boolean wantCondiments() {
        try {
            char want = getUserInput();
            return want == 'y';
        } catch (IOException e) {
            e.printStackTrace();
        }
        return super.wantCondiments();
    }
    private char getUserInput() throws IOException {
        System.out.println("请输入你是否需要添加原料(y/n):");
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        return  (char) in.read();
    }
}
  • 茶水
public class TeaDrinks extends Drinks{
    protected void pourCup() {
        System.out.println("步骤二:添加茶叶冲泡");
    }
    protected void addCondiments() {
        System.out.println("步骤四:放入少量的柠檬");
    }
    @Override
    protected boolean wantCondiments() {
        try {
            char want = getUserInput();
            return want == 'y';
        } catch (IOException e) {
            e.printStackTrace();
        }
        return super.wantCondiments();
    }
    private char getUserInput() throws IOException {
        System.out.println("请输入你是否需要添加原料(y/n):");
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        return  (char) in.read();
    }
}
  • 测试结果
步骤一:正在烧水
步骤二:倒入咖啡粉冲泡
步骤三:等待5分钟
请输入你是否需要添加原料(y/n):
n

步骤一:正在烧水
步骤二:添加茶叶冲泡
步骤三:等待5分钟
请输入你是否需要添加原料(y/n):
y
步骤四:放入少量的柠檬

好莱坞原则

新的设计原则:

  • 好莱坞原则:别调用我们,我们会调用你。(高层组件对待低层组件的方式)

好莱坞原则和模板方法

定义算法的抽象类就是我们的高层组件,它的子类就是低层组件,低层组件无法调用高层组件,减少依赖

  • 依赖倒置原则教我们少用具体实现类,多用接口、抽象。
  • 好莱坞原则是一种创建算法、框架的技巧,减少依赖。

JDK中模板方法

  • 数组的sort方法
  • swing的paint方法

策略模式和模板方法模式

  • 策略模式使用组合,模板方法使用继承
  • 模板方法模式需要更少的对象
  • 策略模式更有弹性(组合),模板方法模式耦合度高,依赖多

代码地址:Github模板方法模式


Java设计模式|策略模式

Java设计模式|观察者模式

Java设计模式|装饰者模式

Java设计模式|工厂模式

Java设计模式|命令模式

Java设计模式|适配器模式和外观模式

Java设计模式|模板方法模式

Java设计模式|迭代器模式和组合模式

Java设计模式|状态模式

Java设计模式|代理模式

Java设计模式|单例模式

Java设计模式|备忘录模式

Java设计模式|访问者模式

Java设计模式|复合模式

Java设计模式|桥接模式

Java设计模式|生成器模式

Java设计模式|享元模式/蝇量模式

Java设计模式|原型模式

Java设计模式|责任链模式

Java设计模式|中介者模式

  • 本文作者: dzou | 微信:17856530567
  • 本文链接: http://www.dzou.top/post/55d3fc38.html
  • 版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明出处!
  • 并保留本声明和上方二维码。感谢您的阅读和支持!