设计模式--模板方法模式C++实现

模板方法模式C++实现

一. 问题

1定义

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

实现方案:将算法/逻辑框架放在抽象基类中,并定义好实现接口,在子类中实现细节接口。

注:策略模式,解决的是相同的问题,只是其方案是将各个接口封装为类,通过委托/组合方式解决问题

 

在面向对象系统的分析与设计过程中常常会遇到这样一种情况:对于某一个业务逻辑(算法实现)在不同的对象中有不同的细节实现,可是逻辑(算法)的框架(或通用的应用算法)是同样的。Template提供了这样的情况的一个实现框架。

2类图

图片 1

二. 模式

3实现

class AbstractClass

{

public:

  void Run()

  {

    DoA();

    DoB();

    DoC();

  }

  virtual void DoA()=0;

  virtual void DoB()=0;

  virtual void DoC()=0;

};

class ConcreteClass:public AbstractClass

{

public:

  void DoA()

  {

    cout << "开车门"<<endl;

  }

  void DoB()

  {

    cout << "关车门"<<endl;

  }

  void DoC()

  {

    cout << "发车走人"<<endl;

  }

};

void Test()

{

  AbstractClass *car = new ConcreteClass();

  car->Run();

}

Template 模式是採用继承的方式实现这一点:将逻辑(算法)框架放在抽象基类中,并定义好细节的接口,子类中实现细节

3成员

基本方法,由子类实现的方法,并且在模板方法中被调用。

模板方法,是一个或者几个,一般是一个具体方法/框架,实现对基本方法的调度,完成固定的逻辑。

图片 2

4应用

①优点

封装不变部分/逻辑框架,扩展可变部分/具体细节

提取公共部分代码,便于维护

行为由父类控制,子类实现-->基本方法子类实现,因此子类可以通过扩展的方式增加相应的功能,符合开闭原则

②缺点

因为模板方法将依赖点到,抽象中的框架实现依赖具体类的细节实现。所以是子类行为影响了父类。在复杂项目中,会造成代码阅读困难。

三. 代码

5 使用场景

多个子类有共有的方法,并且逻辑相同/逻辑相同,细节有差异

对重要,复杂的算法,可以讲核心算法设计为模板方法,周边细节由子类实现

重构时,经常使用的方案,将相同的代码抽象到父类,通过钩子函数约束行为。

[cpp] view plaincopy

6扩展

①对于原定框架中的模板方法,如果存在子类中对某个接口的具有选择性(执行或者不执行),那么在调用时就需要具体判别这种差异性调用。

②对这种选择性,用过钩子,策略模式等方案。判别,调用。然后在子类中实现具体的钩子定义。

  1. //抽象基类,实现了一个模板方法  
  2. class AbstractClass  
  3. {  
  4. public:  
  5.     virtual ~AbstractClass()  
  6.     {  
  7.     }  
  8.   
  9.         //模板方法,仅仅在抽象基类中实现  
  10.     void TemplateMethod()  
  11.     {  
  12.         this->PrimitiveOperation1();  
  13.         this->PrimitiveOperation2();  
  14.     }  
  15.   
  16. protected:  
  17.     virtual void PrimitiveOperation1() = 0;  
  18.   
  19.     virtual void PrimitiveOperation2() = 0;  
  20.   
  21.     AbstractClass()  
  22.     {  
  23.     }  
  24. };  
  25.   
  26. //详细子类,实现操作的特定细节  
  27. class ConcreteClass1:public AbstractClass  
  28. {  
  29. public:  
  30.     ConcreteClass1()  
  31.     {  
  32.     }  
  33.   
  34.     ~ConcreteClass1()  
  35.     {  
  36.     }  
  37.   
  38. protected:  
  39.     void PrimitiveOperation1()  
  40.     {  
  41.         cout<<"ConcreteClass1...PrimitiveOperation1"<<endl;  
  42.     }  
  43.   
  44.     void PrimitiveOperation2()  
  45.     {  
  46.         cout<<"ConcreteClass1...PrimitiveOperation2"<<endl;  
  47.     }  
  48. };  
  49.   
  50. //详细子类,实现操作的特定细节  
  51. class ConcreteClass2:public AbstractClass  
  52. {  
  53. public:  
  54.     ConcreteClass2()   
  55.     {  
  56.     }  
  57.   
  58.     ~ConcreteClass2()  
  59.     {  
  60.     }  
  61.   
  62. protected:  
  63.     void PrimitiveOperation1()  
  64.     {  
  65.         cout<<"ConcreteClass2...PrimitiveOperation1"<<endl;  
  66.     }  
  67.   
  68.     void PrimitiveOperation2()  
  69.     {  
  70.         cout<<"ConcreteClass2...PrimitiveOperation2"<<endl;  
  71.     }  
  72. };  
  73.   
  74.   
  75. int main()  
  76. {  
  77.     AbstractClass* p1 = new ConcreteClass1();  
  78.     AbstractClass* p2 = new ConcreteClass2();  
  79.       
  80.     p1->TemplateMethod();  
  81.     p2->TemplateMethod();  
  82.       
  83.     return 0;  
  84. }  

7狡辩

父类调用子类的方法:

①把子类传递到父类的有残构造函数,然后调用

②使用反射的方式调用

③父类调用子类的静态方法

虽然这几种方式也实现了父类调用子类方法,但是在项目中并不能运用。子类简历框架,子类在重写了父类部分方法后,再调用从父类集成的方法,产生不同的结果。这正是模板方法--曲线救国。

其关键点就是将通用算法封装在抽象基类中,并将不同的算法细节放到子类中实现。

8应用

在开元框架中,模板方法提供了一个抽象类,然后开元框架写一堆子类。如果需要扩展功能,可以继承这个抽象类,然后覆写protected方法,然后调用一个execute(run)方法,就完成功能扩展。

 

本文由开元棋牌发布于操作系统,转载请注明出处:设计模式--模板方法模式C++实现

TAG标签:
Ctrl+D 将本页面保存为书签,全面了解最新资讯,方便快捷。