设计模式C++001__模板方法

设计模式C++001__模板方法

“组件协作”模式:

现代软件专业分工之后的第一个结果就是“框架与应用程序的划分”,组件“协作”模式通过晚绑定,来实现框架与应用程序之间的松耦合。

包括:
模版方法,观察者模式,策略模式

1、模板方法模式:

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

从静态编译的角度看,结构化软件设计流程是符合人们的直觉的,先开发好类库或者库函数。然后我们业务开发的程序员来调用Lib库中的函数。
但是一般库函数是稳定的,业务变更频繁,不同业务对2、4步骤实现会千差万别。


图中红色部分是稳定部分,类库一旦写好,核心功能基本确定。整体系统的运行还需要根据具体业务填充蓝色部分2、4步骤。我们做开发时要想到设计模式的原则:
依赖倒置原则,即上层不应该依赖底层。这里1,3,5就是底层实现,2,4所在的Application是上层业务层。那么我们应该1,3,5依赖2,4所在Application。
即细节应该依赖抽象,而不是抽象依赖细节。

在面向开发过程中,由于有多态的特性,或者类似其他语言运行时的支持,例如C++的多态特性,C语言的函数指针,OC的runtime。一些函数的调用关系被放到了运行时才确定。
这样,就可以将一些步骤延迟到子类,或者运行时来做。

这里就引出了早绑定和晚绑定的概念。正是因为有了晚绑定的概念,库和业务程序之间这种跨时间维度的开发交互成为现实。
库的开发人员只需要知道,2,4步骤将来一定会由外部业务开发人员来实现。我只需要开发好1,3,5.并把调用整体流程的框架搭好就行了。

2、早绑定和晚绑定

//C语言中的函数调用,编译期就已经确定好调用关系-----早绑定
#import <stdio.h>
void printHello(){
  printf("Hello, world!");
}

void printGoodBye(){
  printf("Goodby, world!");
}

void doSomeThing(int type){
  if(type == 0){
    printHello();
  }else{
    printGoodbye();
  }
}

//C语言中 运行时才确定好调用关系 ----晚绑定
#import <stdio.h>
void printHello(){
  printf("Hello, world!");
}

void printGoodBye(){
  printf("Goodby, world!");
}

void doSomeThing(int type){
  void (*func)();//声明一个函数指针,
  if(type == 0){
    func = printHello;
  }else{
    func = printGoodbye;
  }
  func();//这个函数调用的指令,不过待调用的函数地址无法硬编码在指令中,只有在运行时读出来。
}

以结构化的程序开发流程为例:

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

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

    void Step3(){
		//...
    }

    void Step5(){
		//...
    }
};
//Application的开发
//应用程序开发人员
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();

}

面向对象的开发流程

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

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

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

        Step5();

    }
	virtual ~Library(){ }

protected:
	
	void Step1() { //稳定
        //.....
    }
	void Step3() {//稳定
        //.....
    }
	void Step5() { //稳定
		//.....
	}

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

主程序的开发

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

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




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

		delete pLib;
	}
}

3、模板方法模式的定义:

定义一个操作中的算法骨架(稳定),而将一些步骤(变化)延迟到子类中。Template Method使得子类可以不改变(复用)一个算法的结构即可重定义(override)该算法的某些特定步骤。--GoF

结构:

4、要点:

Template Method模式是一种非常基础的设计模式,在面向对象系统中有着大量的应用。它用最简洁的机制(虚函数多态特性)为很多应用程序框架提供了灵活的扩展点,是代码复用方面的基本实现结构。
除了可以灵活应对子步骤的变化外,“不要调用我,让我来调用你”的反向控制结构式Template Method的典型应用。
在具体实现方面,被Template Method调用的虚方法可以具有实现,也可以没有任何实现(抽象方法,纯虚方法),但一般不推荐将他们设置为protected方法。

posted @ 2024-07-25 19:11  wjwdive  阅读(3)  评论(0编辑  收藏  举报