设计模式学习-模板模式

设计模式学习-模板模式

前面的时间学习了5种创建型设计模式和7种结构型设计模式,现在开始学习行为型的设计模式

http://www.runoob.com/design-pattern/template-pattern.html

在模板模式(Template Pattern)中,一个抽象类公开定义了执行它的方法的方式/模板。它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行。这种类型的设计模式属于行为型模式。

模板模式的介绍

意图:定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
主要解决:一些方法通用,却在每一个子类都重新写了这一方法。
何时使用:有一些通用的方法。
如何解决:将这些通用算法抽象出来。
关键代码:在抽象类实现,其他步骤在子类实现。
应用实例:
1、在造房子的时候,地基、走线、水管都一样,只有在建筑的后期才有加壁橱加栅栏等差异。
2、西游记里面菩萨定好的 81 难,这就是一个顶层的逻辑骨架。
3、spring 中对 Hibernate 的支持,将一些已经定好的方法封装起来,比如开启事务、获取 Session、关闭 Session 等,程序员不重复写那些已经规范好的代码,直接丢一个实体就可以保存。
优点: 1、封装不变部分,扩展可变部分。 2、提取公共代码,便于维护。 3、行为由父类控制,子类实现。
缺点:每一个不同的实现都需要一个子类来实现,导致类的个数增加,使得系统更加庞大。
使用场景: 1、有多个子类共有的方法,且逻辑相同。 2、重要的、复杂的方法,可以考虑作为模板方法。
注意事项:为防止恶意操作,在JAVA中一般模板方法都加上 final 关键词。而C++则缺少这种操作。

UML结构图

抽象基类: AbstractClass:抽象基类,定义算法的轮廓
解析: TemplateMethod的关键在于在基类中定义了一个算法的轮廓,但是算法每一步具体的实现留给了派生类.但是这样也会造成设计的灵活性不高的缺点,因为轮廓已经定下来了要想改变就比较难了,这也是为什么优先采用聚合而不是继承的原因。

实现演练

1、对应UML结构图的实现的代码

#include<iostream>
using namespace std;
//抽象基类,定义算法的轮廓
class AbstractClass
{
public:
    AbstractClass(){}
    virtual ~AbstractClass(){}
    //这个函数中定义了算法的轮廓
    void TemplateMethod()
    {
        PrimitiveOperation1();
        PrimitiveOperation2();
    }
protected:
    //纯虚函数;由派生类实现之
    virtual void PrimitiveOperation1()=0;
    virtual void PrimitiveOperation2()=0;
};
//继承自AbstractClass,实现算法
class ConcreteClass:public AbstractClass
{
public:
    ConcreteClass(){}
    virtual ~ConcreteClass(){}
protected:
    virtual void PrimitiveOperation1()
    { 
        cout<<"PrimitiveOperation1 by ConcreteClass"<<endl; 
    }
    virtual void PrimitiveOperation2()
    { 
        cout<<"PrimitiveOperation2 by ConcreteClass"<<endl; 
    }
};
int main()
{
    AbstractClass* pConcreteClass = new ConcreteClass();
    pConcreteClass->TemplateMethod();
    delete pConcreteClass;
    return 0;
}

2、一个实例,进一步加深理解

//步骤 1 创建一个抽象类,它的模板方法被设置为 final。
class Game
{
public:
    Game(){}
    virtual ~Game(){}
    //这个函数中定义了算法的轮廓
    void play()
    {
      //初始化游戏
      initialize();
      //开始游戏
      startPlay();
      //结束游戏
      endPlay();
    }
protected:
    //纯虚函数;由派生类实现之
    virtual void initialize()=0;
    virtual void startPlay()=0;
    virtual void endPlay()=0;
};
//步骤 2 创建扩展了上述类的实体类。
class Cricket:public Game
{
public:
    Cricket(){}
    virtual ~Cricket(){}
protected:
    void endPlay() 
    {
      cout<<"Cricket Game Finished!"<<endl;
    }

    void initialize() 
    {
       cout<<"Cricket Game Initialized! Start playing."<<endl;
    }

    void startPlay() 
    {
       cout<<"Cricket Game Started. Enjoy the game!"<<endl;
    }
};



class Football:public Game 
{
public:
    Football(){}
    virtual ~Football(){}
protected:
   void endPlay() 
   {
      cout<<"Football Game Finished!"<<endl;
   }

   void initialize() 
   {
      cout<<"Football Game Initialized! Start playing."<<endl;
   }

   void startPlay() 
   {
      cout<<"Football Game Started. Enjoy the game!"<<endl;
   }
}
//步骤 3 使用 Game 的模板方法 play() 来演示游戏的定义方式。
int main() 
{
      Game *game = new Cricket();
      game->play();
      cout<<endl;
      game = new Football();
      game->play();        
   }
}

验证输出:
Cricket Game Initialized! Start playing.
Cricket Game Started. Enjoy the game!
Cricket Game Finished!

Football Game Initialized! Start playing.
Football Game Started. Enjoy the game!
Football Game Finished!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值