【设计模式】模板方法模式

【什么是设计模式】

     官方解释:定义一个操作中算法的框架,而将一些步骤延迟到子类中。模板方法模式使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。

  设计模式大咖闫宏解释:模板方法模式是类的行为型模式。准备一个抽象类,将部分逻辑以具体方法以及具体构造函数的形式实现,然后声明一些抽象方法来迫使子类实现剩余的逻辑。不同的子类可以以不同的方式实现这些抽象方法,从而对剩余的逻辑有不同的实现。这就是模板方法模式的用意。

【模板类图】

可以看出,模板方法模式由两部分组成:

         (1) 抽象类(AbstractClass):抽象类实现了模板方法,定义了算法的框架,其中的方法可以是具体方法也可以是抽象方法(其中抽象方法称为基本操作,算法的框架称为模板方法)。

         (2) 具体子类(ConcreteClass):继承抽象类,实现了抽象类中的抽象方法从而完成子类特定的算法,也可以选择是否重写父类中的具体方法。

【模板方法的代码实现】

模板抽象类的实现方法包括三种,分别为:

    (1)抽象方法:由抽象类声明,由具体子类实现。
(2)具体方法:具体方法由抽象类声明并实现,而子类并不实现或置换。
 (3)钩子方法:钩子方法是由抽象类声明并实现,子类会选择是否应用或是否加以扩展。钩子方法一般有两种实现方式。第一种方式是由抽象类给出空实现,即像下边一样:

[java] view plain copy

  1. <span style="font-size:14px;background-color: rgb(255, 255, 102);">//定义钩子方法,空实现  
  2.     public void printQianYan(){};</span>  

    第二种方式可以这样使用挂钩,让其决定里面的代码是否执行:

[java] view plain copy

  1. <span style="font-size:14px;">//我们也可以这样使用挂钩,让其决定里面的代码是否执行  
  2.     if(hook()){    
  3.         //打印前言  
  4.         printQianYan();    
  5.     }    
  6.     @Override    
  7.     public boolean hook() {    
  8.         return false;    
  9.     }  </span> 

【实例】

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

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

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

我们来整理一下流程。

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

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

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

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

抽象类

[java] view plain copy

  1. abstract class Beverage {  
  2.   
  3.   
  4.   
  5.     // 模板方法,决定了算法骨架。相当于TemplateMethod()方法  
  6.   
  7.     public void prepareBeverage() {  
  8.   
  9.         boilWater();  
  10.   
  11.         brew();  
  12.   
  13.         pourInCup();  
  14.   
  15.         if (customWantsCondiments())  
  16.   
  17.         {  
  18.   
  19.             addCondiments();  
  20.   
  21.         }  
  22.   
  23.     }  
  24.   
  25.       
  26.   
  27.     // 共性操作,直接在抽象类中定义  
  28.   
  29.     public void boilWater() {  
  30.   
  31.         System.out.println("烧开水");  
  32.   
  33.     }  
  34.   
  35.       
  36.   
  37.     // 共性操作,直接在抽象类中定义  
  38.   
  39.     public void pourInCup() {  
  40.   
  41.         System.out.println("倒入杯中");  
  42.   
  43.     }  
  44.   
  45.       
  46.   
  47.     // 钩子方法,决定某些算法步骤是否挂钩在算法中  
  48.   
  49.     public boolean customWantsCondiments() {  
  50.   
  51.         return true;  
  52.   
  53.     }  
  54.   
  55.       
  56.   
  57.     // 特殊操作,在子类中具体实现  
  58.   
  59.     public abstract void brew();  
  60.   
  61.       
  62.   
  63.     // 特殊操作,在子类中具体实现  
  64.   
  65.     public abstract void addCondiments();  
  66.   
  67.       
  68.   
  69. }  

具体类

[java] view plain copy

  1. class Tea extends Beverage {  
  2.   
  3.     @Override  
  4.     public void brew() {  
  5.         System.out.println("冲泡茶叶");  
  6.     }  
  7.   
  8.     @Override  
  9.     public void addCondiments() {  
  10.         System.out.println("添加柠檬");  
  11.     }  
  12.       
  13. }  
  14.   
  15. class Coffee extends Beverage {  
  16.   
  17.     @Override  
  18.     public void brew() {  
  19.         System.out.println("冲泡咖啡豆");  
  20.     }  
  21.   
  22.     @Override  
  23.     public void addCondiments() {  
  24.         System.out.println("添加糖和牛奶");  
  25.     }  
  26.       
  27. }  

测试类

[java] view plain copy

  1. public static void main(String[] args) {  
  2.           
  3.     System.out.println("============= 准备茶 =============");  
  4.     Beverage tea = new Tea();  
  5.     tea.prepareBeverage();  
  6.       
  7.     System.out.println("============= 准备咖啡 =============");  
  8.     Beverage coffee = new Coffee();  
  9.     coffee.prepareBeverage();  
  10.       
  11. }  

运行结果

[java] view plain copy

  1. ============= 准备茶 =============  
  2. 烧开水  
  3. 冲泡茶叶  
  4. 倒入杯中  
  5. 添加柠檬  
  6. ============= 准备咖啡 =============  
  7. 烧开水  
  8. 冲泡咖啡豆  
  9. 倒入杯中  
  10. 添加糖和牛奶  

【模板方法的优点及应用场景】

       容易扩展。一般来说,抽象类中的模版方法是不易反生改变的部分,而抽象方法是容易反生变化的部分,因此通过增加实现类一般可以很容易实现功能的扩展,符合开闭原则。

       便于维护。对于模版方法模式来说,正是由于他们的主要逻辑相同,才使用了模版方法,假如不使用模版方法,任由这些相同的代码散乱的分布在不同的类中,维护起来是非常不方便的。

       比较灵活。因为有钩子方法,因此,子类的实现也可以影响父类中主逻辑的运行。但是,在灵活的同时,由于子类影响到了父类,违反了里氏替换原则,也会给程序带来风险。这就对抽象类的设计有了更高的要求。

       在多个子类拥有相同的方法,并且这些方法逻辑相同时,可以考虑使用模版方法模式。在程序的主框架相同,细节不同的场合下,也比较适合使用这种模式。

时间: 2025-01-21 00:19:33

【设计模式】模板方法模式的相关文章

hand first设计模式 -模板方法模式

模板方法模式 : 在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中.模板方法使得子类可以在不改变算法结构的情况下,重新算法.重新定义算法中的某些步骤. 咖啡因饮料超类 Java代码 /** * 咖啡因饮料超类 * @author panxiuyan * */ public abstract class CaffeinBeverage { /** * 制作方法 */ public void perareRecip() { boilWater(); brew(); pourInCup();

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

模板方法模式 定义一个操作中算法的骨架,而将一些步骤延迟到子类中.模板方法使子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤. Template Method Pattern Define the skeleton of an algorithm in an operation, deferring some steps to subclasses. Template Method lets subclasses redefine certain steps of an algorit

设计模式之禅之设计模式-模板方法模式

一:模板方法模式的定义        --->定义一个操作中的算法的框架,而将一些步骤延迟到子类中.使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤.        --->模板方法模式确实非常简单,仅仅使用了Java的继承机制,但它是一个应用非常广泛的模式.其中,AbstractClass叫做抽象模板,它的方法分为两类:        ● 基本方法                基本方法也叫做基本操作,是由子类实现的方法,并且在模板方法被调用.        ● 模板方法   

解读设计模式----模板方法模式(Template Method)

一. 模式概述 摸板方法(Template Method)模式是一种非常简单而又经常使用的设计模式.先创建一个父类,把其中的一个或多个方法留给子类去实现,这实际上就是在使用摸板模式.所谓的摸板模式可以这样来理解:"在一个类中定义一个算法,但将此算法的某些细节留到子类中去实现.换句话说,基类是一个抽象类,那么你就是在使用一种简单形式的摸板模式." 更近一步可以这样来理解:"准备一个抽象类,将部分逻辑以具体方法的形式实现,然后申明一些抽象方法来迫使子类实现剩余的逻辑.不同的子类可

C++设计模式编程中Template Method模板方法模式的运用_C 语言

准备一个抽象类,将部分逻辑以具体方法以及具体构造子的形式实现,然后声明一些抽象方法来迫使子类实现剩余的逻辑.不同的子类可以以不同的方式实现这些抽象方法,从而对剩余的逻辑有不同的实现.这就是模版方法模式的用意. 很多人可能没有想到,模版方法模式实际上是所有模式中最为常见的几个模式之一,而且很多人可能使用过模版方法模式而没有意识到自己已经使用了这个模式.模版方法模式是基于继承的代码复用的基本技术,模版方法模式的结构和用法也是面向对象设计的核心. 模版方法模式需要开发抽象类和具体子类的设计师之间的协作

详解设计模式中的模板方法模式及在C++中的使用_C 语言

模板方法模式是设计模式行为型中最简单的一种设计模式.在实际中你甚至可能经常用到,只是你自己不知道它是一种设计模式罢了. 模板方法模式定义一个操作中的算法的骨架,而将一些步骤延迟到子类中.模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤.角色:抽象类(AbstractClass): 定义抽象的原语操作,具体的子类将重定义它们以实现一个算法,实现一个模板方法,定义一个算法的骨架.该模板方法不仅调用原语操作,也调用定义 具体子类 (ConcreteClass): 实现原语操作以完

举例讲解Java设计模式编程中模板方法模式的运用实例_java

模板方法模式定义为: 在一个方法中定义了一个算法的骨架或者步骤,而将一些步骤延迟到子类中去实现.模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某一些步骤. 模板方法在基类中定义了一个操作的流程顺序,能够保证该步骤按序进行,有一些步骤的具体实现在基类中已经声明,而将一些变化的步骤的具体实现交给了子类去实现,从而就达到了延迟一些步骤到子类中,模板方法一个最大的好处就是能够设定一个业务流程能够按照一定严格的顺序执行,控制了整个算法的执行步骤. 这个方法将算法定义成一组步骤,其中凡是想让

学习php设计模式 php实现模板方法模式_php技巧

一.意图 定义一个操作中的算法的骨架,而将一些步骤延迟到子类中.Template Method 使得子类可以在不改变一个算法的结构的情况下重定义该算法的某些特定的步骤[GOF95]二.模板方法模式结构图 三.模板方法模式中主要角色抽象模板(AbstractClass)角色: 定义一个或多个抽象方法让子类实现.这些抽象方法叫做基本操作,它们是顶级逻辑的组成部分. 定义一个模板方法.这个模板方法一般是一个具体方法,它给出顶级逻辑的骨架,而逻辑的组成步骤在对应的抽象操作中,这些操作将会推迟到子类中实现

学习JavaScript设计模式之模板方法模式_javascript技巧

一.定义 模板方法是基于继承的设计模式,可以很好的提高系统的扩展性. java中的抽象父类.子类 模板方法有两部分结构组成,第一部分是抽象父类,第二部分是具体的实现子类. 二.示例 Coffee or Tea (1) 把水煮沸 (2) 用沸水浸泡茶叶 (3) 把茶水倒进杯子 (4) 加柠檬 /* 抽象父类:饮料 */ var Beverage = function(){}; // (1) 把水煮沸 Beverage.prototype.boilWater = function() { conso

重温设计模式(七)——模板方法模式

1.摘要 在本文中,我们来对模板方法模式做一个全面的了解. 2.求职简讯 呵呵,如果各位不介意,希望在这里做一个求职的广告. 语言方向:Java/C#/VB,语言熟悉程度降序排列. 求职方向:开发,测试等与IT相关工作. 月薪要求:1000元以上 工作地点:北京 3.开门见山 模板方法,定义一个操作中算法骨架,而将一些步骤延迟到子类中去实现. 让我们先来看看模板方法的示意图: 这个模式的本身很容易理解,我就不自己去画了. 我们看到这个模式的关键在于父类中的TemplateMethod()方法,正