【java设计模式】之 模板方法(Template Method)模式

版权声明:尊重博主原创文章,转载请注明出处哦~http://blog.csdn.net/eson_15/article/details/51323902

目录(?)[+]

1. 模板方法的一个实例

        这一节主要来学习一下设计模式中的模板方法模式。我们先来看一个例子:假如现在老板让你做一个汽车的模型,要求只要完成基本功能即可,不考虑扩展性,那你会怎么做呢?我们首先会根据经验设计一个类图:

       由这个类图可知,非常简单的实现了悍马车,该车有两个型号H1和H2。那现在我们开始实现这两个型号的悍马车,首先我们得把抽象类写好,然后两个不同的模型实现类通过简单的继承就可以实现要求。首先看看抽象类的代码:

[java] view plain copy

 

  1. public abstract class HummerModel {  
  2.     public abstract void start(); //发动  
  3.     public abstract void stop();  //停止  
  4.     public abstract void alarm(); //鸣笛  
  5.     public abstract void engineBoom(); //轰鸣  
  6.     public abstract void run(); //车总归要跑  
  7. }  

        简单到不行,下面我们来实现两个悍马的模型:

[java] view plain copy

 

  1. //悍马H1  
  2. public class HummerH1 implements HummerModel {  
  3.   
  4.     @Override  
  5.     public void start() {  
  6.         System.out.println("H1发动……");  
  7.     }  
  8.   
  9.     @Override  
  10.     public void stop() {  
  11.         System.out.println("H1停止……");  
  12.     }  
  13.   
  14.     @Override  
  15.     public void alarm() {  
  16.         System.out.println("H1鸣笛……");  
  17.     }  
  18.   
  19.     @Override  
  20.     public void engineBoom() {  
  21.         System.out.println("H1轰鸣……");  
  22.     }  
  23.   
  24.     @Override  
  25.     public void run() {  
  26.         this.start();  
  27.         this.engineBoom();  
  28.         this.alarm();  
  29.         this.stop();  
  30.     }  
  31. }  
  32.   
  33. //悍马H2  
  34. public class HummerH2 implements HummerModel {  
  35.   
  36.     @Override  
  37.     public void start() {  
  38.         System.out.println("H2发动……");  
  39.     }  
  40.   
  41.     @Override  
  42.     public void stop() {  
  43.         System.out.println("H2停止……");  
  44.     }  
  45.   
  46.     @Override  
  47.     public void alarm() {  
  48.         System.out.println("H2鸣笛……");  
  49.     }  
  50.   
  51.     @Override  
  52.     public void engineBoom() {  
  53.         System.out.println("H2轰鸣……");  
  54.     }  
  55.   
  56.     @Override  
  57.     public void run() {  
  58.         this.start();  
  59.         this.engineBoom();  
  60.         this.alarm();  
  61.         this.stop();  
  62.     }  
  63. }  

        很明显,已经发现代码有点问题了,两个悍马的run方法完全相同。所以这个run方法应该出现在抽象类中,不应该在实现类中,抽象是所有子类的共性封装。所以我们修改一下抽象类:

[java] view plain copy

 

  1. public abstract class HummerModel {  
  2.     public abstract void start(); //发动  
  3.     public abstract void stop();  //停止  
  4.     public abstract void alarm(); //鸣笛  
  5.     public abstract void engineBoom(); //轰鸣  
  6.     public void run() { //车总归要跑  
  7.         this.start();  
  8.         this.engineBoom();  
  9.         this.alarm();  
  10.         this.stop();  
  11.     }  
  12. }  

        这样两个实现类就不用实现run方法了,可以直接拿来用。其实,这就是模板方法模式。

2. 模板方法模式的定义

        模板方法模式很简单,它的定义是:Define the skeleton of an algorithm in an operation, deferring some steps to subclasses. Template Method lets subclasses define certain steps of an algorithm without changing the algorithm's structure. 即定义一个操作中的算法框架,而将一些步骤延迟到子类中,使得子类可以不改变一个算法的结构即可冲定义该算法的某些特定步骤。模板方法模式的通用类图如下:

        模板方法模式确实很简单,仅仅使用了Java的继承机制,但是它是一个应用非常广泛的模式,其中AbstractClass叫做抽象模板,它的方法分为两类:基本方法(由子类去实现)和模板方法(可以有一个或多个,也就是一个框架,实现对基本方法的调度,完成固定的逻辑)。为了防止恶意的操作,一般模板方法上都添加上final关键字,不允许被覆写。我们来看一下AbstractClass模板:

[java] view plain copy

 

  1. public abstract class AbstractClass {  
  2.     //基本方法  
  3.     protected abstract void doSomething();  
  4.     protected abstract void doAnything();  
  5.     //模板方法  
  6.     public void templateMethod() {  
  7.         //调用基本方法,完成相关的逻辑  
  8.         this.doAnything();  
  9.         this.doSomething();  
  10.     }  
  11. }  

        具体实现类就不写了……

3. 模板方法模式的优缺点

      优点:

        1)封装不变部分,扩展可变部分:把认为不变部分的算法封装到父类实现,可变部分则可以通过继承来实现,很容易扩展。

        2)提取公共部分代码,便于维护:上面悍马的例子就是个很好的解释。

        3)行为由父类控制,由子类实现。

      缺点:

        模板方法模式颠倒了我们平常的设计习惯:抽象类负责声明最抽象、最一般的事物属性和方法,实现类实现具体的事物属性和方法。在复杂的项目中可能会带来代码阅读的难度。

4. 模板方法模式的扩展

        还是上面那个悍马的例子,现在老板说这车干嘛跑起来就要鸣笛,太吵了,难道不是应该让用户决定它是否要鸣笛么?好像确实是这样的……那好办,我们可以修改一下抽象模板类中的方法:

[java] view plain copy

 

  1. public abstract class HummerModel {  
  2.     protected abstract void start(); //发动  
  3.     protected abstract void stop();  //停止  
  4.     protected abstract void alarm(); //鸣笛  
  5.     protected abstract void engineBoom(); //轰鸣  
  6.     final public void run() { //车总归要跑  
  7.         this.start();  
  8.         this.engineBoom();  
  9.         if(this.isAlarm()) {//想让它叫就叫,不想就不叫        
  10.             this.alarm();  
  11.         }  
  12.         this.stop();  
  13.     }  
  14.     protected boolean isAlarm() { //我们加了一个判断方法,默认返回true  
  15.         return true;  
  16.     }  
  17. }  

       我们在模板类中增加了一个判断方法来判断是否要鸣笛,现在就好办了,具体实现类只要重写这个方法就可以做到人为控制是否要鸣笛了,下面我们来看一下实现类:

[java] view plain copy

 

  1. public class HummerH1 extends HummerModel {  
  2.   
  3.     private boolean alarmFlag = true; //判断标记  
  4.     @Override  
  5.     public void start() {  
  6.         System.out.println("H1发动……");  
  7.     }  
  8.   
  9.     @Override  
  10.     public void stop() {  
  11.         System.out.println("H1停止……");  
  12.     }  
  13.   
  14.     @Override  
  15.     public void alarm() {  
  16.         System.out.println("H1鸣笛……");  
  17.     }  
  18.   
  19.     @Override  
  20.     public void engineBoom() {  
  21.         System.out.println("H1轰鸣……");  
  22.     }  
  23.       
  24.     @Override  
  25.     protected boolean isAlarm() { //覆写isAlarm方法,返回判断标记  
  26.         return this.alarmFlag;  
  27.     }  
  28.       
  29.     public void setAlarm(boolean isAlarm) { //设置判断标记  
  30.         this.alarmFlag = isAlarm;  
  31.     }  
  32.       
  33. }  

        这个实现很好,我们在实现类中定义一个判断标记,然后对外提供一个public接口setAlarm来让外界设置这个判断标记,这就像是开关一样,想让它ture和false都行。这个isAlarm方法俗称钩子方法。有了钩子方法的模板方法模式才算完美,大家可以想象一下,由子类的一个方法返回值决定公共部分的执行结果,这个是很有吸引力的。我们来测试一下:

[java] view plain copy

 

  1. public class Test {  
  2.     public static void main(String[] args) throws IOException {  
  3.         System.out.println("----H1型悍马----");  
  4.         System.out.println("是否需要喇叭声响? 0-不需要  1-需要");  
  5.         String type = new BufferedReader(new InputStreamReader(System.in)).readLine();  
  6.         HummerH1 h1 = new HummerH1();  
  7.         if(type.equals("0")) {  
  8.             h1.setAlarm(false);  
  9.         }  
  10.         h1.run();  
  11.     }  
  12. }  

        当输入不同的指令后,就会决定不同的动作:即要不要鸣笛,至此,这个模板方法模式就介绍完了。

        相关阅读:http://blog.csdn.net/column/details/des-pattern.html

_____________________________________________________________________________________________________________________________________________________

-----乐于分享,共同进步!

-----更多文章请看:http://blog.csdn.net/eson_15

时间: 2024-09-17 18:18:47

【java设计模式】之 模板方法(Template Method)模式的相关文章

行为型设计模式之模板方法(TEMPLATE METHOD)模式 ,策略(Strategy )模式

1 模板方法(TEMPLATE METHOD)模式: 模板方法模式把我们不知道具体实现的步聚封装成抽象方法,提供一些按正确顺序调用它们的具体方法(这些具体方法统称为模板方法),这样构成一个抽象基类.子类通过继承这个抽象基类去实现各个步聚的抽象方法,而工作流程却由父类来控制.  2 模板方法应用于下列情况: 1) 一次性实现一个算法的不变的部分,并将可变的行为留给子类来实现. 2)各子类中公共的行为应被提取出来并集中到一个公共父类中以避免代码重复.首先识别现有代码中的不同之处,并且将不同之处分离为

设计模式重构应用---Template Method模式

先简单介绍Template Method模式的内容和应用场景. Template Method模式也叫模板方法模式,它把具有特定步骤算法中的某些必要的处理委让给抽象方法 ,通过子类继承对抽象方法的不同实现改变整个算法的行为. 在作为抽象类的父类里,定义了一个具有固定算法并可以细分为多个步骤的模板方法(public), Template Method模式把这些可以被细分的可变步骤抽象为可以被子类重载的抽象方法(protected abstract),并通过在子类中的重载(重新定义),做到无需改变模

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

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

设计模式学习笔记(八)—Template Method模式

<设计模式>一书对Template Method模式是这样描述的: 定义一个操作中算法的骨架,而将一些步骤延迟到子类中.不改变算法的结构而重新定义它的步骤. 我的理解:定义一个抽象类或者说接口,在它的内部定义一些抽象的方法(供TemplateMethod调用的步骤)和一个TemplateMethod方法(非抽象方法),封装了这些抽象方法的接口或抽象类就是骨架.而将它的实现延迟到子类中,也就是用子类实现它.不改变算法的结构而重新定义它的步骤,也就是改写或者实现父类的这些非TemplateMeth

JUnit源码分析 (三)——Template Method模式

在JUnit执行测试时,我们经常需要初始化一些环境供测试代码使用,比如数据库连接.mock对象等等,这些初始化代码应当在每一个测试之前执行并在测试方法运行后清理.在JUnit里面就是相应的setUp和tearDown方法.如果没有这两个方法,那么我们要在每个测试方法的代码内写上一大堆重复的初始化和清理代码,这是多么愚蠢的做法.那么JUnit是怎么让setUp和tearDown在测试执行前后被调用的呢?     如果你查看下TestCase方法,你会发现TestCase和TestSuite的run

Design Pattern: Template Method 模式

  学习是分享和合作式的! 转载请注明出处:http://blog.csdn.net/wdzxl198/article/details/9223275: 文章摘自: http://www.riabook.cn/doc/designpattern/: 不要将设计模式想得高不可攀,好像高手才会使用的东西,事实上如果您在下手程式之前,能稍稍对程式作个分析规划,或多或少都会用到一些模式了,模式不是教条,它只是前人的经验成果,而 Gof 的书则是择前人之精华持续改进而来罢了. Template Metho

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

模式意图 定义一个类的框架,当它有不同的类时,再具体实现. 比如,我们设计一个跨系统的客户端软件,Windows需要一套展现类,Linux需要一套,mac还需要一套.这样,只需要抽取他们的共同操作编程一个框架类,具体使用到哪个系统时,再使用对应的类,有点像C++里面的模板. 应用场景 1 一次性实现一个类的不变部分,其他的部分留到子类实现. 2 各个子类提取公共部分成为超类 3 控制子类的扩展. 模式结构 AbstractClass 抽象类框架 abstract class AbstractCl

Java设计模式详解之门面模式(外观模式)_java

门面模式(Facade Pattern)也叫外观模式,它隐藏系统的复杂性,并向客户端提供一个可以访问系统的接口.这种类型的设计模式属于结构型模式,它向现有的系统添加一个接口,来隐藏系统的复杂性,为子系统中的一组接口提供了一个统一的高层访问接口,这个接口使得子系统更容易被访问或使用.这种模式涉及到一个单一的类,该类提供了客户端请求的简化方法和对现有系统类方法的委托调用. 简而言之,就是把一堆复杂的流程封装成一个接口供给用户更简单的使用,这个设计模式里有三个角色: 1)门面角色( facade ):

java设计模式系列之装饰者模式_java

何为装饰者模式 (Decorator)? 动态地给一个对象添加一些额外的职责.就增加功能来说,Decorator 模式相比生成子类更为灵活.一.结构 Component : 定义一个对象接口,可以给这些对象动态地添加职责. interface Component { public void operation(); } ConcreteComponent : 实现 Component 定义的接口. class ConcreteComponent implements Component { @O

Java设计模式透析:模板方法(Template Method)

今天你还是像往常一样来上班,一如既往地开始了你的编程工作. 项目经理告诉你,今天 想在服务器端增加一个新功能,希望写一个方法,能对Book对象进行处理,将Book对象的所有字段以 XML格式进行包装,这样以后可以方便与客户端进行交互.并且在包装开始前和结束后要打印日志, 这样方便调试和问题定位. 没问题!你觉得这个功能简直是小菜一碟,非常自信地开始写起 代码. Book对象代码如下: public class Book { private String bookName; private int