Java设计模式之模板方法模式(Template Method)

一、含义

  定义一个算法中的操作框架,而将一些步骤延迟到子类中。使得子类可以不改变算法的结构即可重定义该算法的某些特定步骤,不同的子类可以以不同的方式实现这些抽象方法,从而对剩余的逻辑有不同的实现。

二、模式中的角色

  抽象类(AbstractClass):实现了模板方法,定义了算法的骨架。

  具体类(ConcreteClass):实现抽象类中的抽象方法,已完成完整的算法

三、类图及源码

模板方法模式的通用类图非常简单,仅仅使用了Java的继承机制,但它是一个非常广泛的模式。其类图如下,其中AbstractClass叫做抽象模板,它的方法分为两类:

  • 基本方法:是由子类实现的方法,并且在模板方法被调用。(一般都加上final关键字,防止被覆写)
  • 模板方法:可以有一个或几个,一般是一个具体方法,也就是一个框架,实现对基本方法的调用,完成固定的逻辑。(抽象模板中的基本方法尽量设计为protected类型,符合迪米特法则,不需要暴露的属性或方法尽量不要设置为protected类型。实现类若非必要,尽量不要扩大父类中的访问权限)

               

上述通用类图的源码如下:

 1 public abstract class AbstractClass {
 2     protected abstract void doAnything();
 3     protected abstract void doSomething();
 4     public final void templateMethod(){
 5         /*
 6          * 调用基本方法,完成相关的逻辑
 7          */
 8         this.doAnything();
 9         this.doSomething();
10     }
11 }
12 public class ConcreteClass1 extends AbstractClass {
13 
14     @Override
15     protected void doAnything() {
16         // TODO Auto-generated method stub
17         //子类实现具体
18     }
19 
20     @Override
21     protected void doSomething() {
22         // TODO Auto-generated method stub    
23     }
24 }
25 public class ConcreteClass2 extends AbstractClass {
26 
27     @Override
28     protected void doAnything() {
29         // TODO Auto-generated method stub
30         //子类实现具体
31     }
32 
33     @Override
34     protected void doSomething() {
35         // TODO Auto-generated method stub    
36     }
37 }

四、优缺点

1、模板方法模式的优点

  • 封装不变部分,扩展可变部分。把认为不变部分的算法封装到父类中实现,而可变部分的则可以通过继承来继续扩展。
  • 提取公共部分代码,便于维护。
  • 行为由父类控制,子类实现。

2、模板方法模式的缺点

  按照设计习惯,抽象类负责声明最抽象、最一般的事物属性和方法,实现类负责完成具体的事务属性和方法,但是模板方式正好相反,子类执行的结果影响了父类的结果,会增加代码阅读的难度。

五、使用场景

  • 多个子类有共有的方法,并且逻辑基本相同
  • 重要、复杂的算法,可以把核心算法设计为模板方法,周边的相关细节功能则由各个子类实现
  • 重构时,模板方法是一个经常使用的方法,把相同的代码抽取到父类中,然后通过构造函数约束其行为

六、实例

以准备去学校所要做的工作(prepareGotoSchool)为例,假设需要分三步:穿衣服(dressUp),吃早饭(eatBreakfast),带上东西(takeThings)。学生和老师要做得具体事情肯定有所区别。

抽象类AbstractClass

 1 public abstract class AbstractPerson{  
 2      //抽象类定义整个流程骨架  
 3      public void prepareGotoSchool(){  
 4           dressUp();  
 5           eatBreakfast();  
 6           takeThings();  
 7      }  
 8      //以下是不同子类根据自身特性完成的具体步骤  
 9      protected abstract void dressUp();  
10      protected abstract void eatBreakfast();  
11      protected abstract void takeThings();  
12 }

具体类ConcreteClass

 1     public class Student extends AbstractPerson{  
 2          @Override  
 3          protected void dressUp() {  
 4               System.out.println(“穿校服");  
 5          }  
 6          @Override  
 7          protected void eatBreakfast() {  
 8               System.out.println(“吃妈妈做好的早饭");  
 9          }  
10       
11          @Override  
12          protected void takeThings() {  
13               System.out.println(“背书包,带上家庭作业和红领巾");  
14          }  
15     }  
 1     public class Teacher extends AbstractPerson{  
 2          @Override  
 3          protected void dressUp() {  
 4               System.out.println(“穿工作服");  
 5          }  
 6          @Override  
 7          protected void eatBreakfast() {  
 8               System.out.println(“做早饭,照顾孩子吃早饭");  
 9          }  
10       
11          @Override  
12          protected void takeThings() {  
13               System.out.println(“带上昨晚准备的考卷");  
14          }  
15     }  

测试类:

1 public class Client {  
2      public static void main(String[] args) {  
3      Student student = new Student()  
4      student.prepareGotoSchool();  
5   
6      Teacher teacher  = new Teacher()  
7      teacher.prepareGotoSchool();  
8      }  
9 }
原文地址:https://www.cnblogs.com/zq-boke/p/8514566.html