设计模式-Template Method

仅作参考

前言

GOF-23 模式分类:

-》从目的来看:

        •创建型(Creational)模式:将对象的部分创建工作延迟到子类或者其他对象,从而应对需求变化为对象创建时具体类型实现引来的冲击。

        •结构型(Structural)模式:通过类继承或者对象组合获得更灵活的结构,从而应对需求变化为对象的结构带来的冲击。

        •行为型( Behavioral )模式:通过类继承或者对象组合来划分 类与对象间的职责,从而应对需求变化为多个交互的对象带来 的冲击。
-》从范围来看:
       
         •类模式处理类与子类的静态关系。
        • 对象模式处理对象间的动态关系。

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

此处只对模式特点进行分类,并不表明该模式不具备其他特点。

组件协作: •Template Method(模板模式) •Observer / Event(观察者/事件模式)
                   •Strategy(策略模式)
单一职责:  •Decorator(装饰模式) • Bridge(桥接模式)
对象创建:   •Factory Method(工厂方法)•Abstract Factory(抽象工厂) • Prototype(原型模式)
                   • Builder(生成器模式)
对象性能: •Singleton(单例模式) • Flyweight(享元模式) 
接口隔离:   Façade (外观模式)  •Proxy(代理模式)•Mediator(中介者模式)
                 •Adapter(适配器模式)
状态变化: •Memento(备忘录模式)• State(状态模式)
数据结构: •Composite(组合模式)•Iterator(迭代器模式)
                   •Chain of  Resposibility(责任链模式)
行为变化: •Command(命令模式)• Visitor(访问者模式)
领域问题: Interpreter (解释器模式)

重构获得模式Refactoring to Patterns

面向对象设计模式是“好的面向对象设计”,所谓“好的面向对象设计”指是那些可以满足“ 应对变化 提高复用 ”的设计。
现代软件设计的特征是“ 需求的频繁变化 ”。设计模式的要点是 寻找变化点,然后在变化点处应用设计模式,从而来更好地应对 需求的变化”.“什么时候、什么地点应用设计模式”比“理解设 计模式结构本身”更为重要。
设计模式的应用不宜先入为主,一上来就使用设计模式是对设计模式的最大误用。没有一步到位的设计模式。敏捷软件开发实践提倡的“Refactoring to Patterns ”是目前普遍公认的最好的使用设计模式的方法。

重构关键技法

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

“组件协作”模式:

现代软件专业分工之后的第一个结果是“ 框架 应用程序 的划 分”,“组件协作”模式通过晚期绑定,来实现框架与应用程序之间的松耦合,是二者之间协作时常用的模式。
典型模式包括模板模式、策略模式以及观察者模式

Template Method 模式:

动机(Motivation

在软件构建过程中,对于某一项任务,它常常有 稳定的 整体操作 结构,但各个子步骤却有很多 改变的 需求,或者由于固有的原因 (比如框架与应用之间的关系)而无法和任务的整体结构同时实现。
如何在确定稳定操作结构的前提下,来灵活应对各个子步骤的变化或者晚期实现需求?

具体案例:

//程序库开发人员
class Library{

public:
	void Step1(){
		//...
	}

    void Step3(){
		//...
    }

    void Step5(){
		//...
    }
};

在该类中,程序开发人员设定了固定的方法step1,step3,step4;

//应用程序开发人员
class Application{
public:
//由于应用需求增加的功能函数
	bool Step2(){
		//...
    }

    void Step4(){
		//...
    }
};

int main()
{
	Library lib();
	Application app();

	lib.Step1();

	if (app.Step2()){
		lib.Step3();
	}

	for (int i = 0; i < 4; i++){
		app.Step4();
	}

	lib.Step5();

}

可以看到,主函数在启用Application时进行调用的步骤,假设该应用调用过程相对一定,那么对于多个应用程序来说,重复的调用相同函数会导致极大的资源浪费,不如实现运行函数,变化部分由子类具体实现,更改代码如下:

//程序库开发人员
class Library{
public:
	//稳定 template method,
    void Run(){
        
        Step1();

        if (Step2()) { //支持变化 ==> 虚函数的多态调用
            Step3(); 
        }

        for (int i = 0; i < 4; i++){
            Step4(); //支持变化 ==> 虚函数的多态调用
        }

        Step5();

    }
//虚析构函数原因:当子类进行删除时,调用对应的析构函数
	virtual ~Library(){ }

protected:
	/**之所以设置为proteced,是因为这些step函数只有在处于一个流程或过程中
    才有意义**/
	void Step1() { //稳定
        //.....
    }
	void Step3() {//稳定
        //.....
    }
	void Step5() { //稳定
		//.....
	}

	virtual bool Step2() = 0;//变化
    virtual void Step4() =0; //变化
};

可以看出,在修改后,具体的调用流程由library中的Run函数实现,而Run函数通过虚函数的多态调用实现不同应用的调用

//应用程序开发人员
class Application : public Library {
protected:
	virtual bool Step2(){
		//... 子类重写实现
    }

    virtual void Step4() {
		//... 子类重写实现
    }
};




int main()
	{
	    Library* pLib=new Application();
	    lib->Run();

		delete pLib;
	}
}
结构化软件设计流程
在未改变前:
在改变后:

早绑定与晚绑定

library先于application创建,在未改变前,程序主流程实现要依靠library中的函数,此称为早绑定

而在改变后,具体的内容依旧由application提供,但是具体的实现流程是固定的,依靠于application的具体函数实现.

模式定义:

定义一个操作中的算法的骨架 ( 稳定 ) ,而将一些步骤 延迟 (变化 ) 到子类中。 Template Method 使得子类可以不改变 (复用 ) 一个算法的结构即可重定义 (override 重写 ) 该算法的某些特定步骤。
此处延迟指将具体的函数实现交友子类完成

结构:

要点总结:

    1. Template Method模式是一种非常基础性的设计模式,在面向对象系统中有着大量的应用。它用最简洁的机制(虚函数的多态性)为很多应用程序框架提供了灵活的扩展点,是代码复用方面的基本实现结构。(扩展点指子类可以重定义操作具体的行为)

2.除了可以灵活应对子步骤的变化外,“不要调用我,让我来调用你”的反向控制结构是Template Method的典型应用。

3.在具体实现方面,被Template Method调用的虚方法可以具有实现,也可以没有任何实现(抽象方法、纯虚方法),但一般推荐将它们设置为protected方法。

模板方法的适用性

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

各子类中公共的行为应被提取出来,并集中到一个公共父类中以避免代码重复。

控制子类扩展。(钩子操作(hook operations))

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值