简说设计模式——模板方法模式

1、什么是模板方法模式

  所谓模板方法模式,其实很简单,能够从模板的角度考虑,就是一个对模板的应用,就比如老师出试卷,每一个人的试卷都是同样的,即都是从老师的原版试卷复印来的,这个原版试卷就是一个模板,可每一个人写在试卷上的答案都是不同的,这就是模板方法模式,是否是很好理解。它的主要用途在于将不变的行为从子类搬到超类,去除了子类中的重复代码。git

  模板方法模式(TemplateMethod),定义一个操做中的算法的骨架,而将一些步骤延迟到子类中,使得子类能够不改变一个算法的结构便可重定义该算法的某些特定步骤。UML结构图以下:算法

   其中,AbstractClass实现类一个模板方法,定义了算法的骨架,具体子类将重定义PrimitiveOperation以实现一个算法的步骤;而ConcreteClass实现了PrimitiveOperation以完成算法中与特定子类相关的步骤。ide

   1. 抽象模板类

  定义一个模板方法来组合PrimitiveOperation1()和PrimitiveOperation2()两个方法造成一个算法,而后让子类重定义这两个方法。函数

 1 public abstract class AbstractClass {
 2 
 3     public abstract void PrimitiveOperation1();
 4     public abstract void PrimitiveOperation2();
 5     
 6     public void TemplateMethod() {
 7         PrimitiveOperation1();
 8         PrimitiveOperation2();
 9     }
10     
11 }

   2. 具体模板类

  这里定义两个具体模板类,ConcreteClassA及ConcreteClassB来进行测试,继承抽象模板类,实现具体方法。测试

 1 public class ConcreteClassA extends AbstractClass {
 2 
 3     @Override
 4     public void PrimitiveOperation1() {
 5         System.out.println("具体方法A方法1实现");
 6     }
 7 
 8     @Override
 9     public void PrimitiveOperation2() {
10         System.out.println("具体方法A方法2实现");
11     }
12 
13 }

   3. Client客户端

  经过调用模板方法来分别获得不一样的结果。spa

 1 public class Client {
 2 
 3     public static void main(String[] args) {
 4         AbstractClass abstractClass;
 5         
 6         abstractClass = new ConcreteClassA();
 7         abstractClass.TemplateMethod();
 8         
 9         abstractClass = new ConcreteClassB();
10         abstractClass.TemplateMethod();
11     }
12     
13 }

   运行结果以下:code

  

2、模板方法模式的应用

  1. 什么时候使用

  • 有一些通用的方法时

  2. 方法

  • 将通用算法抽象出来

  3. 优势

  • 封装不变部分,扩展可变部分
  • 提取公共部分代码,便于维护
  • 行为由父类控制,子类实现

  4. 缺点

  • 每个不一样的实现都须要一个子类实现,致使类的个数增长,使得系统更加庞大

  5. 使用场景

  • 有多个子类共有的方法,且逻辑相同
  • 重要的、复杂的方法,能够考虑做为模板方法
  • 重构时,模板方法模式是一个常常使用到的模式,把相同的代码抽取到父类中,经过钩子函数约束其行为

  6. 应用实例

  • 作试卷,你们题目都是同样的,只是答案不一样
  • 对于汽车,车从发动到停车的顺序是相同的,不一样的是引擎声、鸣笛声等
  • 造房时,地基、走线、水管都同样,只有在建筑后期才有差别

  7. 注意事项

  • 为防恶意操做,通常模板方法都加上final关键字

3、模板方法模式的实现

  下面就以上方提到的作试卷为例,具体实现一下以说明如何将模板方法模式应用在实际案例中,UML图以下:blog

  1. 试卷抽象类

  以下在抽象类中定义三个普通方法表明试卷的问题,再定义三个抽象方法代码试题答案。继承

 1 public abstract class TestPaper {
 2 
 3     //问题
 4     public void question1() {
 5         System.out.println("1+1=?");
 6         System.out.println("答案:" + answer1());
 7     }
 8     
 9     public void question2() {
10         System.out.println("2+2=?");
11         System.out.println("答案:" + answer2());
12     }
13     
14     public void question3() {
15         System.out.println("3+3=?");
16         System.out.println("答案:" + answer3());
17     }
18     
19     //答案
20     protected abstract String answer1();
21     
22     protected abstract String answer2();
23     
24     protected abstract String answer3();
25 }

   2. 具体试卷

  下面定义一个学生甲的试卷,学生乙的试卷与之相比只是返回的答案不一样。get

 1 public class TestPaperA extends TestPaper {
 2 
 3     @Override
 4     protected String answer1() {
 5         return "2";
 6     }
 7 
 8     @Override
 9     protected String answer2() {
10         return "4";
11     }
12 
13     @Override
14     protected String answer3() {
15         return "6";
16     }
17     
18 }

   3. Client客户端

  基于同一个模板,学生甲乙分别进行答题,获得不同的结果。

 1 public class Client {
 2 
 3     public static void main(String[] args) {
 4         System.out.println("学生甲的试卷:");
 5         TestPaper studentA = new TestPaperA();
 6         studentA.question1();
 7         studentA.question2();
 8         studentA.question3();
 9         
10         //分隔符
11         System.out.println("------------------------------------------------");
12         
13         System.out.println("学生乙的试卷:");
14         TestPaper studentB = new TestPaperB();
15         studentB.question1();
16         studentB.question2();
17         studentB.question3();
18     }
19     
20 }

   运行结果以下:

  

  当咱们要完成在某一细节层次一致的一个过程或一系列步骤,但其个别步骤在更详细的层次上的实现可能不一样时,咱们一般考虑用模板方法模式来处理。

 

  源码地址:https://gitee.com/adamjiangwh/GoF

相关文章
相关标签/搜索