您的位置:首页 > 其它

设计模式之模板模式 template method

2013-02-10 22:06 288 查看
1.概述


在面向对象开发过程中,通常我们会遇到这样的一个问题:我们知道一个算法所需的关键步骤,并确定了这些步骤的执行顺序。但是某些步骤的具体实现是未知的,或者说某些步骤的实现与具体的环境相关。

例子1:银行业务办理流程

在银行办理业务时,一般都包含几个基本固定步骤:

取号排队->办理具体业务->对银行工作人员进行评分。

取号取号排队和对银行工作人员进行评分业务逻辑是一样的。但是办理具体业务是个不相同的,具体业务可能取款、存款或者转账。


2.问题


如何保证架构逻辑的正常执行,而不被子类破坏 ?


3.解决方案


模板方法:定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。 T模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。(Template Method Pattern:Definethe skeleton
of an algorithm in an operation,deferring some steps tosubclasses.Template Methodletssubclasses
redefine certain steps of an algorithmwithoutchanging the algorithm's structure. )

1)模板方法模式是基于继承的代码复用基本技术,模板方法模式的结构和用法也是面向对象设计的核心之一。在模板方法模式中,可以将相同的代码放在父类中,而将不同的方法实现放在不同的子类中。
2)在模板方法模式中,我们需要准备一个抽象类,将部分逻辑以具体方法以及具体构造
函数的形式实现,然后声明一些抽象方法来让子类实现剩余的逻辑。不同的子类可以以不同的方式实现这些抽象方法,从而对剩余的逻辑有不同的实现,这就是模板
方法模式的用意。模板方法模式体现了面向对象的诸多重要思想,是一种使用频率较高的模式。


4.适用性


模板方法应用于下列情况:

• 1) 一次性实现一个算法的不变的部分,并将可变的行为留给子类来实现。

• 2)各子类中公共的行为应被提取出来并集中到一个公共父类中以避免代码重复。首先识别现有代码中的不同之处,并且将不同之处分离为新的操作。最后,用一个调用这些新的操作的模板方法来替换这些不同的代码。

• 3)控制子类扩展。模板方法只在特定点调用“ hook”操作 ,这样就只允许在这些点进行扩展。


5.结构






6.模式的组成


抽象类(AbstractClass): 定义抽象的原语操作(primitive operation) ,具体的子类将重定义它们以实现一个算法, 实现一个模板方法,定义一个算法的骨架。该模板方法不仅调用原语操作,也调用定义

具体子类 (ConcreteClass): 实现原语操作以完成算法中与特定子类相关的步骤。


7.效果



模板方法模式的优点:

1)模板方法模式在一个类中形式化地定义算法,而由它的子类实现细节的处理。

2)模板方法是一种代码复用的基本技术。它们在类库中尤为重要,它们提取了类库中的公共行为。

3)模板方法模式导致一种反向的控制结构,这种结构有时被称为“好莱坞法则” ,即“别找我们,,我们找你”通过一个父类调用其子类的操作(而不是相反的子类调用父类),通过对子类的扩展增加新的行为,符合“开闭原则”
模板方法模式的缺点:

每个不同的实现都需要定义一个子类,这会导致类的个数增加,系统更加庞大,设计也更加抽象,但是更加符合“单一职责原则”,使得类的内聚性得以提高。


8.实现

我们使用银行业务实现,添加了hook方法,客户自己觉得评价服务。

<?php

/**

* 模板方法模式:

*

* @author guisu

*/

/**

* 抽象类

*/

abstract class AbstractBank

{

private $_number ;

/**

*模板方法

* 因为子类不能覆写一个被定义为final的方法。从而保证了子类的逻辑永远由父类所控制。

*

*/

public final function templateMethodProcess()

{

$this->takeNumber();

$this->transact();

if($this->isEvaluateHook()) {

$this->evaluateHook();

}

}

/**

* 基本方法—具体方法

* 取号

*

*/

private function takeNumber()

{

return ++$this->_number;

}

/**

* //基本方法—抽象方法

*

*/

protected abstract function transact();

/**

* 基本方法—钩子方法

*

*/

protected function evaluateHook() {

echo ' evaluateHook<br/>';

}

/**

* 基本方法—钩子方法

*/

protected function isEvaluateHook() {

return true;

}

}

/**

* 具体子类:存款

*/

class ConcreteDeposit extends AbstractBank

{

public function transact() {

//实现代码

echo 'Deposit', '<br>';

}

}

/**

* 具体子类:取款

*/

class ConcreteWithdraw extends AbstractBank

{

public function transact() {

//实现代码

echo 'Withdraw', '<br>';

}

}

/**

* 具体子类:转账

*/

class ConcreteTrancfer extends AbstractBank

{

public function transact() {

//实现代码

echo 'Trancfer', '<br>';

}

}

$c = new ConcreteTrancfer();

$c->templateMethodProcess(); 、
http://blog.csdn.net/hguisu/article/details/7564039
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: