Java API 设计模式之模板方法(Template Method)

模板方法也涉及了算法。策略设计模式允许若干个对象包含各不同的算法,但模板方法设计模式要求所有的对象共享由超类定义的单一算法。

     比如说,我们在策略设计模式中讨论过,TextDisplay、BarGraphDisplay和PieChartDisplay等类的对象运用相同的基础算法来获取和显示数据----从BankStatementData对象那里获取所有的对账单,分析对账单并显示数据。模板方法设计模式允许我们创建一个叫做BankStatementDisplay的超类,提供用来显示数据的中心算法。在这个例子中,这个算法包含了抽象方法getData、parseData和displayData。类TextDisplay、BarGraphDisplay和PieChartDisplay扩展类BankStatementDisplay,继承这个算法,从而每一个对象可以使用相同的算法。然后,每一个BankStatementDisplay子类按照一种与子类具体相关的方式来覆盖每一个方法,因为每个类彼此之间实现算法的方式是不同的。比如说,类TextDisplay、BarGraphDisplay和PieChartDisplay可以完全一样的获取和分析数据,但它们显示数据的形式是完全不同的。

     模板方法设计模式使得我们可以将这一算法扩展到其他的BankStatementDisplay子类中----比如,我们可以创建诸如LineGraphDisplay、3DimensionalDisplay等这样的类,它们使用继承自超类BankStatmentDisplay的相同算法。

 

意图:

     定义一个操作中某个算法的框架,将算法某些步骤的实现推迟到子类中实现。模板方法可以使子类重新定义一个算法的特定的某个步骤而不需要修改算法的结构。

动机:

     OpenDocument定义了打开一个文档的每一个步骤:检查该文档是否能被打开,创建于应用有关的Document对象,将它加入到它的文档集合中,并且从一个文件中读取该Document。

     我们称OpenDocument为一个模板方法。一个模板方法用一些抽象的操作来定义一个算法,子类将重新定义这些操作以提供具体的行为。通过使用抽象操作定义一个算法的一些步骤,模板方法确定了这些操作出现的先后顺序,但是允许Application和Document子类改变这些步骤来满足他们的各自的需求。

 

实现:

     考虑一个支持在屏幕上绘图的类View,View类强制其子类遵循一个不变的规则:一个view只有在成为焦点之后,才可以在这个view上绘图。成为焦点需要设置合适的特定的绘制状态(如设定颜色和字体)。我们可以使用一个Display 模板方法来设置这个焦点状态。View定义两个具体操作,SEtFocus和ResetFocus,分别设定和清除绘图状态。View的钩子操作DoDisplay执行具体的绘制。Display在调用DoDisplay前调用SetFocus以设定绘图状态;在DoDisplay之后调用ResetFocus以释放绘图状态。

void View::Display() {

     SetFocus();

     DoDisplay();

     ResetFocus();

}

 

为维持不变性,View的客户通常调用Display,而View的子类通常重写DoDisplay。

View本身的DoDisplay什么也不做:

void View::DoDisplay();

子类重定义DoDisplay以增加它们特定的绘图行为:

void MyView::DoDisplay() {

     // render the view's contents

}

 

关于模板方法的说明:

     模板方法设计模式使得父类强制其子类遵循一种不变的结构。

     有时候子类可以通过重定义父类的操作来扩展该操作的行为,期间可显式地调用父类操作。

     void DerivedClass::Operation(){

          PraentClass::Operation();

          //...

          // DerivedClass extended behavior

     }

不幸的是,人们很容易忘记去调用被继承的行为。我们可以将这样一个操作转换为一个模板方法,以使父类可以对子类的扩展方式进行控制。也就是,在父类的模板方法中调用钩子操作。这样子类只可以扩展父类的钩子操作。不能扩展其他部分。对子类的扩展实现了控制。

     模板方法导致了一种反向的控制结构,这种结构有时被称为“好莱坞法则”,即“别找我们,我们找你”。这指得是一个父类调用一个子类的操作。

posted @ 2013-08-24 11:05  free_thinker  阅读(550)  评论(0编辑  收藏  举报