zoukankan      html  css  js  c++  java
  • 模板方法模式学习笔记

    模板方法的实现要素:抽象基类和具体子类

    抽象基类:(1)基本方法:共有的方法,用private修饰

         (2)抽象方法:只知道原则,不知道具体实现,要延迟到子类中实现,用protected abstract修饰

           (3)可选的钩子:具体的子类可以自行决定是否挂钩以及如何挂钩,从而影响算法的实现,用protected修饰

           (4)Template方法:封装了所有子类共同遵循的算法框架,用final修饰,不让子类覆盖重写。

                     模板方法定义成final,即表示子类可以替换掉父类中的可变逻辑,但不能改变掉整体逻辑结构。(好莱坞原则)

    具体子类:(1)实现基类中的抽象方法

           (2)可选的覆盖钩子方法,来更加个性化来影响算法的局部行为。

    总结:

    准备一个抽象类,将部分逻辑以具体方法的形式实现,然后声明一些抽象方法交由子类实现剩余逻辑,用钩子方法给予子类更大的灵活性。最后将方法汇总构成一个不可改变的模板方法。

    模板方法模式的适用场景:

    (1)算法或操作遵循相似的逻辑

    (2)重构时(把相同的代码抽取到父类中)

    (3)重要,复杂的算法,核心算法设计为模板算法

    模板方法模式的优点:

    (1)封装性好

    (2)复用性好

    (3)屏蔽细节

    (4)便于维护

    模板方法模式的缺点:

    (1)继承(Java语言只支持单继承),但我们重构一个系统时,假如有些类已经继承了相关父类,那就无法再继承模板方法的抽象基类。

    简单代码示例如下:

    /**
    * 抽象基类,为所有子类提供一个算法框架
    *
    * 提神饮料
    *
    * @author zhx
    *
    */
    public abstract class RefreshBeverage {

    /*
    * 制备饮料的模版方法 封装了所有子类共同遵循的算法框架
    */
    public final void prepareBeverageTemplate() {
    // 步骤1:将水煮沸
    boilWater();
    // 步骤2:泡制饮料
    brew();
    // 步骤3:将饮料倒入杯中
    pourInCup();

    if(isCustomerWantsCondiments()) {
    // 步骤4:加入调味料
    addCondiments();
    }

    }

    /*
    * Hook,钩子函数,提供一个默认或空的实现
    * 具体的子类可以自行决定是否挂钩以及如何挂钩
    * 询问用户是否加入调料
    */
    protected boolean isCustomerWantsCondiments() {
    return true;
    }

    /*
    * 基本方法,将水煮沸
    */
    private void boilWater() {
    System.out.println("将水煮沸");
    }

    /*
    * 抽象的基本方法,泡制饮料
    */
    protected abstract void brew();

    /*
    * 基本方法,将饮料倒入杯中
    */
    private void pourInCup() {
    System.out.println("将饮料倒入杯中");
    }

    /*
    * 抽象的基本方法:加入调味料
    */
    protected abstract void addCondiments();

    }

    /**
    * 具体子类,提供了制备咖啡的具体实现
    * @author zhx
    *
    */
    public class Coffee extends RefreshBeverage {

    @Override
    protected void brew() {
    System.out.println("用沸水冲泡咖啡");
    }

    @Override
    protected void addCondiments() {
    System.out.println("加入糖和牛奶");
    }

    }

    /**
    * 具体子类:提供了制备茶的具体实现
    * @author zhx
    *
    */
    public class Tea extends RefreshBeverage{

    @Override
    protected void brew() {
    System.out.println("用80℃的热水浸泡茶叶5分钟");
    }

    @Override
    protected void addCondiments() {
    System.out.println("加入柠檬");
    }

    /*
    * 子类通过覆盖的形式选择挂载钩子函数
    * @see edu.bnuz.zhx.design_pattern.template.RefreshBeverage#isCustomerWantsCondiments()
    */
    @Override
    protected boolean isCustomerWantsCondiments() {
    return false;
    }

    }

    public class RefreshBeverageTest {

    public static void main(String[] args) {

    System.out.println("制备咖啡中...");
    RefreshBeverage coffee = new Coffee();
    coffee.prepareBeverageTemplate();
    System.out.println("咖啡制备完成...");

    System.out.println("-----------------------------------");
    System.out.println("制备茶中...");
    RefreshBeverage tea = new Tea();
    tea.prepareBeverageTemplate();
    System.out.println("茶制备完成...");
    }

    }

  • 相关阅读:
    玩转 SpringBoot 2 快速整合 | FreeMarker篇
    微服务简单说
    玩转 SpringBoot 2 快速整合 | JSP 篇
    SpringBoot中获取微信用户信息从未如此简单!
    玩转 SpringBoot 2 快速整合 Filter
    oc语言的Foundation框架(学习笔记1)
    【PyInstaller安装及使用】将py程序转换成exe可执行程序
    【Django】Apache上运行单个Django项目,mod_wsgi配置
    【Django】基于Django架构网站代码的目录结构
    拖延症与自控力
  • 原文地址:https://www.cnblogs.com/houxi/p/4565268.html
Copyright © 2011-2022 走看看