模板模式-类行为型模式

来源:互联网 发布:手持式网络测试仪 编辑:程序博客网 时间:2024/05/17 22:29

意图:

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

本质:固定算法骨架,通过定制模板,把算法步骤固定下来,可以由自己实现,可以由子类实现,还可通过回调机制来让其他类来实现。

动机

一个模板方法用一些抽象的操作定义一个算法,而子类重定义这些操作以提供具体的行为。

通过使用抽象操作定义一个算法中的一些步骤,模板方法确定了它们的先后顺序,但它允许子类改变这些具体步骤以满足各自的需求。

适用性

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

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

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

结构:

 

参与者:

AbstractClass(抽象类):

1定义抽象的原语操作,具体的子类将重定义它们以实现一个算法的各步骤。

2实现一个模板方法,定义一个算法的骨架。模板方法不仅调用原语操作,也调用定义在AbstractClass或其他对象中的操作。

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

协作:

ConcreteClassAbstractClass来实现算法中不变的步骤

效果:

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

模板方法导致一种反向的控制结构:父类调用子类的操作,而不是相反。

模板方法调用以下类型的操作:

1具体的操作:抽象类中自己的方法,不用子类实现

2具体的AbstractClass的操作:对子类有用的操作,例如子类中公共的操作

3原语操作:纯虚函数,自己不实现,子类必须实现。

4 Factory Method操作:如果需要得到某些对象的实例,可以通过工厂方法模式来存取,把具体的构建对象的实现延迟到子类中去。

5钩子操作:它提供了缺省的行为,紫泪在必要时进行扩展。一个钩子操作的缺省操作通常是一个空操作。

在模板方法中应指明哪些操是钩子操作(可以被重定义)以及哪些是抽象操作(必须被重定义)

实现:

1使用C++访问控制C++中,一个模板方法调用的原语操作可以被定义为保护成员。这保证它只被模板方法调用。必须重定义的原语操作须定义为纯虚函数。模板方法自身不需被重定义,因此可将模板方法定义为一个非虚成员函数。

2尽量减少原语操作 定义模板方法的一个重要目的是尽量减少一个子类具体实现该算法时必须重定义的那些原语操作的数目。需要重定义的操作越多,客户程序就越冗长。

3命名约定:可以给应被重定义的那些操作的名字加上一个前缀以识别它们。

相关模式:

FactoryMethod:常被模板方法调用。

Strategy:模板方法使用继承来改变算法的一部分。Strategy使用委托来改变整个算法。模板算法封装的是算法的骨架,算法骨架不变,变化的是算法的具体实现,策略模式是把某个具体实现算法封装起来,所有封装的算法对象是等价的,可以相互替换。

可以在模板方法中使用策略模式,把那些变化的算法步骤通过使用策略模式来实现,但是具体选取哪个由外部决定,但整体算法步骤是模板方法定义的。


模式基本代码:

//模板方法#include <iostream>using namespace std;//抽象模板,定义并实现了一个模板方法 class AbstractClass{public:    //一些抽象行为,可以到子类中去实现     virtual void PrimitiveOperation1() = 0;    virtual void PrimitiveOperation2() = 0;        //模板方法,给出了逻辑骨架,而逻辑的组成是一些相应的    //抽象操作,这些都推迟到子类实现了     void TemplateMethod()    {        PrimitiveOperation1();        PrimitiveOperation2();    }}; //ConcreteClass:实现父类所定义的一个或多个抽象方法,//每一个AbstractClass都可以有任意多个ConcreteClass与之对象。class ConcreteClassA : public AbstractClass{public:    void PrimitiveOperation1()    {        cout << "具体类A方法1实现" << endl;    }        void PrimitiveOperation2()    {        cout << "具体类A方法2实现" << endl;    }}; class ConcreteClassB : public AbstractClass{public:    void PrimitiveOperation1()    {        cout << "具体类B方法1实现" << endl;    }        void PrimitiveOperation2()    {        cout << "具体类B方法2实现" << endl;    }};int main(){    AbstractClass *c;    c = new ConcreteClassA;    c->TemplateMethod();        c = new ConcreteClassB;    c->TemplateMethod();        system("pause");     return 0;}


0 0