设计模式学习笔记--模板方法(Template Method)模式

来源:互联网 发布:智能手环要下什么软件 编辑:程序博客网 时间:2024/05/20 11:49


写在模式学习之前


       什么是设计模式:在我们进行程序设计时,逐渐形成了一些典型问题和问题的解决方案,这就是软件模式;每一个模式描述了一个在我们程序设计中经常发生的问题,以及该问题的解决方案;当我们碰到模式所描述的问题,就可以直接用相应的解决方法去解决这个问题,这就是设计模式。

       设计模式就是抽象出来的东西,它不是学出来的,是用出来的;或许你根本不知道任何模式,不考虑任何模式,却写着最优秀的代码,即使以“模式专家”的角度来看,都是最佳的设计,不得不说是“最佳的模式实践”,这是因为你积累了很多的实践经验,知道“在什么场合代码应该怎么写”,这本身就是设计模式。

       有人说:“水平没到,学也白学,水平到了,无师自通”。诚然,模式背熟,依然可能写不出好代码,更别说设计出好框架;OOP理解及实践经验到达一定水平,同时也意味着总结了很多好的设计经验,但"无师自通",却也未必尽然,或者可以说,恰恰是在水平和经验的基础上,到了该系统的学习一下“模式”的时候了,学习一下专家总结的结果,印证一下自己的不足,对于提高水平还是很有帮助的。

       本系列的设计模式学习笔记,实际是对于《Java与模式》这本书的学习记录。


模板方法模式的定义


准备一个抽象类,将部分逻辑以具体方法以及具体构造的形式实现,然后声明一些抽象方法来迫使子类实现剩余的逻辑。不同的子类可以以不同的方法实现这些抽象的方法,从而对剩余的逻辑有不同的实现。这就是模板方法模式的用意。

实际上,模板方法模式,是利用的对抽象类的继承。这是OOP的三大特征(继承、抽象、重载)之一。在我们的模式中,利用继承思想的不多,大多是利用模式之间的关系,这是模板方法模式比较特别的地方。

模板方法模式需要开发抽象类和开发具体子类的设计师之间的协作。一个设计师负责给出一个算法的轮廓和骨架,另一些设计师则负责给出这个算法的各个逻辑步骤。代表这些具体逻辑步骤的方法称作基本方法( primitive method);而将这些基本方法汇总起来的方法叫做模板方法(template method),这个设计模式的名字就是由此而来。

模板方法所代表的行为称为顶级行为,其逻辑称为顶级逻辑。


模板方法的结构


结构图




所涉及的角色


(1)抽象模板(Abstract Template):定义了一个或多个抽象操作,以便让子类实现。这些抽象操作叫做基本操作,它们是一个顶级逻辑的组成步骤;定义并实现了一个模板方法,而逻辑组成步骤在响应的抽象操作中,推迟到子类实现。顶级逻辑也有可能调用一些具体方法。

(2)具体模板(Concrete Templa):实现父类所定义的一个或多个抽象方法,它们是一个顶级逻辑的组成步骤;每一个抽象模板角色都可以有任意多个具体模板角色与之对应,而每一个具体模板角色都可以给出这些抽象方法(也就是顶级逻辑的组成步骤)的不同实现,从而使得顶级逻辑的实现各不相同。


代码实现


abstract class AbstractClass{//模板方法的声明和实现public void templateMethod(){//调用基本方法(由子类实现)doOp1();//调用基本方法(由子类实现)doOp2();//调用基本方法(已经)实现doOp3();}protected abstract void doOp1();protected abstract void doOp2();protected final void doOp3(){};}class ConcreteClass extends AbstractClass{public void doOp1(){System.out.println("doOp1();");}public void doOp2(){System.out.println("doOp2();");}}

模板方法在代码重构中的应用


模板方法模式可以作为方法层次上的代码重构(Code Refactor)的一个重要手段:

(1)可以将大方法打破,拆成一个模板方法模式。

(2)建立取值方法。

(3)建立常量方法。

(4)如此反复。即以上3个步骤的反复,直到所有的基本方法都变成基本上一样的令人满意的细粒度(granularity),而且所有的常数都放到了常量方法里面。

(5)以多态性取代条件转移。

(6)实施委派。

对一个继承的等级结构做重构时,一个应当遵从的原则便是将行为尽量移动到结构的高端,而将状态尽量移动到结构的低端:

(1)应当根据行为而不是状态定义一个类。也就是说,一个类的实现首先建立在行为的基础之上,而不是建立在状态的基础之上。

(2)在实现行为时,使用抽象状态而不是用具体状态。如果一个行为涉及到对象的状态时,使用间接的引用而不是直接的引用。换言之,应当使用取值方法而不是直接引用属性。

(3)给操作划分层次。一个类的行为应当放到一个小组的核心方法(kernel methods)里面,这些方法可以很方便地在子类中加以置换。

(4)将状态属性的确认推迟到子类中。不要在抽象类中过早地声明属性变量,应将它们尽量地推迟到子类中去声明。在抽象超类中,如果需要状态属性的话,可以调用抽象的取值方法,而将抽象的取值方法的实现放到具体子类中。

如果能够遵从这样的原则,那么就可以在等级结构中将接口与实现分隔开来,将抽象与具体分隔开来,从而保证代码可以最大限度地被复用。


更多了解


(1)所谓“好莱坞原则”,指的是娱乐公司对娱乐项目的完全控制。应聘的演艺人员只是被动地服从总项目的流程安排,在需要的时候完成流程中的一个具体环节,这体现了模板模式的关键:子类可以置换掉父类的可变部分,但是子类却不可以改变模板方法所代码的顶级逻辑。

(2)每当定义一个新的子类时,不要按照流程控制的思路去想,而应当按照“责任”的思路去想。换言之,应当考虑有哪些操作是必须置换掉的,哪些操作是可以置换掉的,以及哪些操作是不可以置换掉的。使用模板方法模式使这项责任变得清晰。

0 0
原创粉丝点击