第3节 模板方法模式

一、模式分类

1. 从目的来看

1.1 创建型模式:指创建对象的模式,抽象勒实例化的过程,帮助系统独立于如何创建爱你、组合和表示;
1.2 结构型模式:为解决怎样组装现有类,设计他们的交互方式,而达到一定的功能;
1.3 行为型模式:在不同对象之间划分责任和算法的抽象化,重点关注它们是如何相互租用;

三者的关系

1) 创建模式为其它两种模式的使用提供环境,好比Visual Studio软件提供了.NET的环境和 操作平台,使各种语言能够随心所欲地在平台上编译执行;
2) 结构型模式侧重于接口的使用,它做的一切工作都是对象或类之间的交互,提供一个门,成就一个你来我往、协同合作的地球村;
3) 行为模型,顾名思义,侧重于具体行为,所以概念中才会出现职责分类和算法通信等内容.
将三者结合起来称为故事——中美合作的故事,其中:创建型模式提供国际环境,无战争、求发展;结构型模式为中美合作提供理由,即和平时代的互利共赢; 行为模式就具体到两个大国之间是如何合作,比如经济合作、文化合作等.

2. 从范围来看

2.1 类模式处理类与子对象的静态关系;
2.2 对象模式处理对象间的动态关系;

二、从封装变化角度对模式分类

  • 组件写作: 模板模式、策略模式、观察者(事件)模式
  • 单一职责: 装饰者模式、桥模式
  • 对象创建: 工厂模式、抽象模式、原型模式、构建者模式
  • 对象性能: 单例模式、Flyweight
  • 接口隔离: 外观模式、代理模式、中介者模式、适配器模式
  • 状态变化: 备忘录模式、状态模式
  • 数据结构: 复合模式、迭代器模式、职责链模式
  • 行为变化: 命令模式、观察者模式
  • 领域问题: 解释器模式

三、重构获得模式

  1. OOP设计模式是"好的OOP对象设计",所谓好的OOP对象设计,指可应对变化,提高复用率;
  2. 现代软件设计的特征是"需求的频繁变化",设计模式的目标是"寻找变化点",然后在变化点处应用设计模式设计模式的难点在于"知道when,where使用设计模式",而不是看懂别人的设计模式代码,或者生搬硬套设计模式;
  3. 设计模式不宜先入为主,不应一遇到问题就套用设计模式,这可能导致模式的误用,设计模式是逐渐迭代出来的;

四、推荐书籍

  • 《重构—改善既有代码的设计》
  • 《重构与模式》

五、重构关键技法

静态->动态 早绑定->晚绑定 继承->组合 编译时依赖->运行时依赖 紧耦合->松耦合

六、template设计模式

1.template模式设计动机

1.1 在软件构建中,对于某些任务常有稳定的整体结构,但各子步骤确有很多改变的需求,或者由于固有的原因而无法与任务的整体结构同时实现
1.2 如何在确定稳定操作结构的前提下,来灵活应对各个子步骤的变化或者晚期实现需求?

2. 程序示例

很多时候,项目代码中需要我们把些许凋以某种流程串联起来.

#include <stdio.h>

// 1. 程序库的开发人员(先开发)
class Library {
public:
    Library()  {}
    ~Library() {}
public: 
    void Step1(){
	// 完成某一项任务的几个步骤,步骤1...
    }
    void Step3(){
	// 完成某一项任务的几个步骤,步骤3...
    }
    void Step5(){
	// 完成某一项任务的几个步骤,步骤5...
    }
};

// 2. 应用程序开发人员(后开发)
class Application
{
public:
    Application() {}
    ~Application(){}
public:
    bool Setp2() { return false; }
    void Step4()  {}
private:
};

// 3. 主函数中按照特有的流程将功能组合起来
int main()
{
    Library lib;
    Application app;
    lib.Step1();                               // 第一步

    if (app.Setp2())  lib.Step3();             // 第二步、第三步
    for (int i = 0; i < 4; i++) app.Step4();   // 第四步
    lib.Step5();                               // 第五步

    return 0;
}

3. 使用模板方法模式重构

#include <stdio.h>

// 1. 程序库的开发人员(先开发)
class Library
{
public:
    Library()  {}
    // C++ 良好习惯:父类的析构函数都写成虚的
    virtual ~Library() {}                   // 虚析构函数:删除父对象时,子对象也删除,不写成虚析构函数则子类对象不能析构
protected:
    void Step1() {}
    void Step3() {}
    void Step5() {}
protected:
    virtual bool Step2() = 0;               // 虚函数,作用多态时,调用子类方法
    virtual void Step4() = 0;
public:
    // 稳定的template method
    void Run()
    {
	Step1();
	if (Step2())  Step3();
	for (int i = 0; i < 4; i++) Step4();
	Step5();
    }
};

//  2. 应用程序开发人员(后开发)
class Application:public Library
{
public:
    Application()  {}
    ~Application() {}
protected:
    virtual bool Step2(){
	// 子类开发人员重写
	return false;
    }
    virtual void Step4() {
	// 子类开发人员重写
    }
};

// 3. 主函数中按照特有的流程将功能组合起来
int main()
{
    Library *lib = new Application();
    lib->Run();
    delete lib; 

    return 0;
}

4. 重构分析

  • 重构前代码: Application(开发完)调用Library(开发早),称为早绑定
  • 重构后代码: Library(开发早)调用Applicaiton(开发晚),称为晚绑定

模板模式总结:

  • 即早期定义骨架(稳定),支持细节(变化)延迟在子类中定义,即可提高父类的复用,并且子类可以重新定义细节;
  • 稳定的代码使用实函数,可变的写成虚函数,前提条件是父类有一个稳定的构架,不然则不适合模板模式;
  • 启发:模板模式给我们的启示就是做项目的时候一定要学会分析代码中哪些是稳定的,哪些部分不是稳定的;

5. 要点总结

  1. Template Method是一种非常基础性的设计模式,在OOP对象系统中有大量的应用。它用最简洁的机制(虚函数多台),为很多App提供了灵活的扩展点,是代码复用的基本实现结构;
  2. 除了灵活应对子步骤的变换外,"不要调用我,让我来调用你"的反向控制结构是模板模式的电影应用;
  3. 具体实现上,被模板模式调用的虚方法可以具有实现,也可以没有任何实现(抽象方法、纯虚方法),但一般推荐将他们设置为protected方法.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值