JAVA 设计模式 模板方法模式

简介: 定义 模板方法模式 (Template Method) 定义了一个操作中的算法的骨架,而将部分步骤的实现在子类中完成。 模板方法模式使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。

定义


模板方法模式 (Template Method)
定义了一个操作中的 算法的骨架,而将 部分步骤的实现在子类中完成。
模板方法模式使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。

模板方法模式是所有模式中最为常见的几个模式之一,是基于继承代码复用的基本技术。,没有关联关系。

因此,在模板方法模式的类结构图中,只有继承关系

模板方法模式需要开发抽象类和具体子类的设计师之间的协作。一个设计师负责给出一个算法的轮廓和骨架,另一些设计师则负责给出这个算法的各个逻辑步骤。

代表这些具体逻辑步骤的方法称做 基本方法(primitive method);而将这些基本方法汇总起来的方法叫做 模板方法(template method),这个设计模式的名字就是从此而来。

 


结构


图-模板方法模式结构图

AbstractClass : 抽象类,定义并实现一个模板方法。这个模板方法定义了算法的骨架,而逻辑的组成步骤在相应的抽象操作中,推迟到子类去实现。顶级逻辑也有可能调用一些具体方法。

abstract  class AbstractClass {
     public  abstract  void PrimitiveOperation1();
     public  abstract  void PrimitiveOperation2();
    
     public  void TemplateMethod() {
        PrimitiveOperation1();
        PrimitiveOperation2();
    }
}
ConcreteClass : 实现实现父类所定义的一个或多个抽象方法。
class ConcreteClassA  extends AbstractClass {
    @Override
     public  void PrimitiveOperation1() {
        System.out.println("具体A类方法1");
    }

    @Override
     public  void PrimitiveOperation2() {
        System.out.println("具体A类方法2");
    }
}

class ConcreteClassB  extends AbstractClass {
    @Override
     public  void PrimitiveOperation1() {
        System.out.println("具体B类方法1");
    }

    @Override
     public  void PrimitiveOperation2() {
        System.out.println("具体B类方法2");
    }    
}
测试代码
public  class TemplateMethodPattern {
     public  static  void main(String[] args) {
        AbstractClass objA =  new ConcreteClassA();
        AbstractClass objB =  new ConcreteClassB();    
        objA.TemplateMethod();
        objB.TemplateMethod();
    }
}



要点


模板方法模式中的三类角色
1、具体方法(Concrete Method)

2、抽象方法(Abstract Method)

3、钩子方法(Hook Method)

三类角色的关联

在模板方法模式中,首先父类会定义一个算法的框架,即实现算法所必须的所有方法。

其中,具有共性的代码放在父类的具体方法中。

各个子类特殊性的代码放在子类的具体方法中。但是父类中需要有对应抽象方法声明。

钩子方法可以让子类决定是否对算法的不同点进行挂钩。

总结

使用模板方法模式可以将代码的公共行为提取,以达到复用的目的。

而对于特殊化的行为在子类中实现。父类的模板方法可以控制子类中的具体实现。

子类无需了解整体算法框架,只需实现自己的业务逻辑即可。

 

 

实例


模板方法模式应用场景十分广泛。

《Head First》的模板方法模式章节里列举了一个十分具有代表性的例子。 

现实生活中,茶和咖啡是随处可见的饮料。冲泡一杯茶或冲泡一杯咖啡的过程是怎样的?

我们来整理一下流程。

泡茶:
烧开水 ==> 冲泡茶叶 ==> 倒入杯中 ==> 添加柠檬
泡咖啡:
烧开水 ==> 冲泡咖啡 ==> 倒入杯中 ==> 添加糖和牛奶

由以上处理步骤不难发现,准备这两种饮料的处理过程非常相似。我们可以使用模板类方法去限定制作饮料的算法框架。

其中相同的具有共性的步骤(如烧开水、倒入杯中),直接在抽象类中给出具体实现。

而对于有差异性的步骤,则在各自的具体类中给出实现。

抽象类
abstract  class Beverage {

     //  模板方法,决定了算法骨架。相当于TemplateMethod()方法
     public  void prepareBeverage() {
        boilWater();
        brew();
        pourInCup();
         if (customWantsCondiments())
        {
            addCondiments();
        }
    }
    
     //  共性操作,直接在抽象类中定义
     public  void boilWater() {
        System.out.println("烧开水");
    }
    
     //  共性操作,直接在抽象类中定义
     public  void pourInCup() {
        System.out.println("倒入杯中");
    }
    
     //  钩子方法,决定某些算法步骤是否挂钩在算法中
     public  boolean customWantsCondiments() {
         return  true;
    }
    
     //  特殊操作,在子类中具体实现
     public  abstract  void brew();
    
     //  特殊操作,在子类中具体实现
     public  abstract  void addCondiments();
    
}
具体类
class Tea  extends Beverage {

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

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

class Coffee  extends Beverage {

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

    @Override
     public  void addCondiments() {
        System.out.println("添加糖和牛奶");
    }
    
}
测试代码
public  static  void main(String[] args) {
        
    System.out.println("============= 准备茶 =============");
    Beverage tea =  new Tea();
    tea.prepareBeverage();
    
    System.out.println("============= 准备咖啡 =============");
    Beverage coffee =  new Coffee();
    coffee.prepareBeverage();
    
}
运行结果
============= 准备茶 =============
烧开水
冲泡茶叶
倒入杯中
添加柠檬
============= 准备咖啡 =============
烧开水
冲泡咖啡豆
倒入杯中
添加糖和牛奶



 

推荐

本文属于 JAVA设计模式系列

 

 

参考资料

《大话设计模式》

《HeadFirst设计模式》

 

 

目录
相关文章
|
算法 Python
利用Python判断一个数是否为完全平方数
利用Python判断一个数是否为完全平方数
1460 0
|
存储 Java C++
怎样定义和引用二维数组
怎样定义和引用二维数组
532 2
|
存储 小程序 数据库管理
【python基础知识】14.图书管理系统的搭建(类与对象实操)
【python基础知识】14.图书管理系统的搭建(类与对象实操)
670 0
Pyside6-第九篇-QTextEdit多行文本编辑器
Pyside6-第九篇-QTextEdit多行文本编辑器
1057 0
|
数据采集 监控 JavaScript
工厂生产管理系统MES十大核心功能模块
MES提供了对生产现场的实时可视化,帮助企业管理生产计划、物料追踪、工艺控制、产品质量和生产设备等方面的工作。
932 11
|
SQL Java 关系型数据库
【JAVA基础篇教学】第十六篇:Java连接和操作MySQL数据库
【JAVA基础篇教学】第十六篇:Java连接和操作MySQL数据库
|
异构计算
硬件描述语言
硬件描述语言
562 1
|
存储 自然语言处理 编译器
【编译原理】词法分析:C/C++实现
【编译原理】词法分析:C/C++实现
795 1
|
存储 Java
Java中的ArrayList的设计思想与底层原理剖析
Java中的ArrayList的设计思想与底层原理剖析
397 1
|
缓存 负载均衡 算法