博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
简说设计模式——模板方法模式
阅读量:5875 次
发布时间:2019-06-19

本文共 3729 字,大约阅读时间需要 12 分钟。

一、什么是模板方法模式

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

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

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

   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客户端

  通过调用模板方法来分别得到不同的结果。

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 }

   运行结果如下:

  

二、模板方法模式的应用

  1. 何时使用

  • 有一些通用的方法时

  2. 方法

  • 将通用算法抽象出来

  3. 优点

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

  4. 缺点

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

  5. 使用场景

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

  6. 应用实例

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

  7. 注意事项

  • 为防恶意操作,一般模板方法都加上final关键字

三、模板方法模式的实现

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

  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. 具体试卷

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

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     @Override14     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://www.cnblogs.com/adamjwh/p/10919149.html

你可能感兴趣的文章
WinForm程序中两份mdf文件问题的解决
查看>>
【转】唯快不破:创业公司如何高效的进行产品研发管理
查看>>
Spark RDD、DataFrame原理及操作详解
查看>>
程序计数器、反汇编工具
查看>>
Android N: jack server failed
查看>>
007-Shell test 命令,[],[[]]
查看>>
关于Linux系统使用遇到的问题-1:vi 打开只读(readonly)文件如何退出保存?
查看>>
pandas 按照某一列进行排序
查看>>
在WPF中如何使用RelativeSource绑定
查看>>
Map的深浅拷贝的探究
查看>>
XSLT语法 在.net中使用XSLT转换xml文档示例
查看>>
如何将lotus 通讯簿导入到outlook 2003中
查看>>
WinForm 应用程序中开启新的进程及控制
查看>>
前端工程师的职业发展路线在哪?
查看>>
IOS 内存警告 Memory warning level
查看>>
[转]PAC Manager: Ubuntu 上强大的 SSH 帐号管理工具,可取代 SecureCRT_Miracle_百度空间...
查看>>
顺序容器 (2)string类型操作
查看>>
转载:我最近的研究成果(IGeometry.Project and IGeometry.SpatialReference)
查看>>
提示框
查看>>
HDOJ1233 畅通工程之一(最小生成树-Kruscal)
查看>>