被说了很多遍的设计模式---模板方法模式

来源:互联网 发布:开淘宝店卖什么比较好 编辑:程序博客网 时间:2024/05/21 22:39

[把你的理性思维慢慢变成条件反射]

本文,我们讲介绍模板方法模式,文章主题结构与上文一致。惯例,先来看看我们示例工程的环境:

操作系统:win7 x64

其他软件:eclipse mars,jdk7

-------------------------------------------------------------------------------------------------------------------------------------

经典问题:

相似的多个过程处理方法,函数,事件等等。

思路分析:

要点一:过程处理的相似性。

要点二:过程处理的差异性。

示例工程:


错误写法(1):

创建ProcessA.java文件,具体内容如下:

package com.csdn.ingo.gof_Template;public class ProcessA {public void cp1() {System.out.println("concrete process 1");System.out.println("concrete process A");}public void cp2() {System.out.println("concrete process 2");System.out.println("concrete process A");}public void cp3() {System.out.println("concrete process 3");System.out.println("concrete process A");}}

创建ProcessB.java文件,具体内容如下:

package com.csdn.ingo.gof_Template;public class ProcessB {public void cp1() {System.out.println("concrete process 1");System.out.println("concrete process B");}public void cp2() {System.out.println("concrete process 2");System.out.println("concrete process B");}public void cp3() {System.out.println("concrete process 3");System.out.println("concrete process B");}}
创建Window.java文件,具体内容如下:

package com.csdn.ingo.gof_Template;public class Window {public static void main(String[] args) {System.out.println("----------Process A-----------");ProcessA pa = new ProcessA();pa.cp1();pa.cp2();pa.cp3();System.out.println("----------Process B-----------");ProcessA pb = new ProcessA();pb.cp1();pb.cp2();pb.cp3();}}

错误原因:

对于ProcessA,ProcessB两个文件中的相似代码完全没有处理,导致客户端产生大量重复代码。违反“开闭原则”。

错误写法(2):


创建Process.java文件,具体内容如下:

package com.csdn.ingo.gof_Template.one;public class Process {public void cp1() {System.out.println("concrete process 1");}public void cp2() {System.out.println("concrete process 2");}public void cp3() {System.out.println("concrete process 3");}}
创建ConcreteProcessA.java,ConcreteProcessB.java文件,具体内容如下:

package com.csdn.ingo.gof_Template.one;public class ConcreteProcessA extends Process{public void cp1(){super.cp1();System.out.println("concrete process A");}public void cp2(){super.cp2();System.out.println("concrete process A");}public void cp3(){super.cp3();System.out.println("concrete process A");}}
创建Window.java文件,具体内容如下:

package com.csdn.ingo.gof_Template.one;public class Window {public static void main(String[] args) {System.out.println("----------ConcreteProcessA-----------");ConcreteProcessA pa = new ConcreteProcessA();pa.cp1();pa.cp2();pa.cp3();System.out.println("----------ConcreteProcessB-----------");ConcreteProcessB pb = new ConcreteProcessB();pb.cp1();pb.cp2();pb.cp3();}}

错误原因:

在第一种写法的基础上,虽然做出了适当的改进,但是,请各位看官仔细观察具体子类中的代码实现,我们发现其中还有一句输出语句。在输出语句中,除了字符A,B的不同,其他内容完全一致。因此,我们还需要进一步抽象。

推荐写法:


创建Process.java文件,具体内容如下:

package com.csdn.ingo.gof_Template.two;public class Process {public void cp1(){System.out.println("concrete process 1");System.out.println("concrete process:" + oper());}public void cp2(){System.out.println("concrete process 2");System.out.println("concrete process:" + oper());}public void cp3(){System.out.println("concrete process 3");System.out.println("concrete process:" + oper());}protected String oper() {return "";}}
创建ConcreteProcessA.java,ConcreteProcessB.java文件,具体内容如下:

package com.csdn.ingo.gof_Template.two;public class ConcreteProcessB extends Process {@Overridepublic String oper() {return "B";}}
创建Window.java文件,具体内容如下:

package com.csdn.ingo.gof_Template.two;public class Window {public static void main(String[] args) {System.out.println("----------ConcreteProcessA-----------");Process pa = new ConcreteProcessA();pa.cp1();pa.cp2();pa.cp3();System.out.println("----------ConcreteProcessB-----------");Process pb = new ConcreteProcessB();pb.cp1();pb.cp2();pb.cp3();}}

推荐原因:

在第二种写法的基础之上,我们再次将子类的部分内容进行抽象。结果,子类当中仅保留差异化的部分内容,实现最大程度的简化。

模式总结:

标准UML结构图:


概念总结:

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

组成部分:AbstractClass(抽象类),ConcreteClass(具体子类)。

模式功能扩展:

对于抽象类内部而言,可以存在三种类型的方法:

  1. 抽象方法:具体实现可由子类完成。
  2. 具体方法:在抽象类内部完成,供其他具体方法调用。
  3. 钩子方法:在抽象类中有两种实现方式:(作用:在模板方法模式中,由于面向对象的多态性,子类对象在运行时将覆盖父类对象,子类中定义的方法也将覆盖父类中定义的方法。因此,程序在运行时,具体子类的基本方法将覆盖父类中定义的基本方法,子类的钩子方法也将覆盖父类的钩子方法,从而可以通过在子类中实现的钩子方法对父类方法的执行进行约束,实现子类对父类行为的反向控制。
    1. 布尔型函数:供过程中的某些操作进行过程判断。
    2. 空函数:交给具体子类完成。作用是:保证编译通过。

示例代码:

package com.csdn.ingo.gof_Template.three;public abstract class AbstractClass {//抽象方法public abstract void PrimitiveOperation1();public abstract void PrimitiveOperation2();//模板方法public void TemplateMethod(){PrimitiveOperation1();PrimitiveOperation2();PrimitiveOperation3();System.out.println("");}//具体方法public void PrimitiveOperation3(){if(isLast()){ ... }}//布尔型钩子方法public boolean isLast(){return true;}//空函数钩子方法public  void emptyMethod(){}}

反思:

应用场景:

在一个复杂的算法,过程处理当中,存在固定不变的部分,有限范围的可变部分。并且,固定部分能够狗此案够出来,可变部分能够交给其子类来处理。

需要子类来决定父类当中的某个函数是否执行,实现子类对父类的反向控制。

优点:

父类当中定义过程执行的顺序,子类决定过程执行的细节。满足“单一职责原则”,“开闭原则”。

有效实现代码复用。方便抽象公共的行为,子类当中保留差异化。

能够实现有效的反向控制。

缺点:

对父类中的抽象方法,钩子方法。都需要实现相应的子类实现。有可能导致子类数量过多。

抽象层级可能多级存在,不易于学习与维护。

-------------------------------------------------------------------------------------------------------------------------------------

至此,被说了很多遍的设计模式---模板方法模式 结束


参考资料:

图书:《大话设计模式》

其他博文:http://blog.csdn.NET/lovelion/article/details/7563445



0 0
原创粉丝点击