首页 > 编程语言 >设计模式C++001__模板方法

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

时间:2024-07-25 19:20:51浏览次数:13  
标签:__ ... 调用 开发人员 void 绑定 C++ Application 设计模式

设计模式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方法。

标签:__,...,调用,开发人员,void,绑定,C++,Application,设计模式
From: https://www.cnblogs.com/wjw-blog/p/18312166

相关文章

  • 设计模式C++002__策略模式
    设计模式C++002__策略模式1、动机:在软件构建过程中,某些对象使用的算法是多种多样的,经常改变,如果将这些算法都编码到对象中,将会使对象变得异常复杂;而且有时候支持不使用的算法也是一个性能负担。?如何在运行时根据需要透明地更改对象的算法?将算法与对象本身解耦,从而避免上述问题?......
  • 设计模式C++003__观察者模式
    设计模式C++003__观察者模式1、动机:在软件构建过程中,我们需要为某些对象建立一种“通过依赖关系”--一个对象(目标对象)的状态发生改变,所有的依赖对象(观察者对象)都将得到通知。如果这样的依赖关系过于紧密,将使得软件不好抵御变化。?使用面向对象技术,可以将这种依赖关系弱化,并形成......
  • NOIP2024/7/25模拟赛
    T4题意:答案对\(2^{16}\)取模。分析:根节点\(1\)选到\(1\)的概率为\(\frac{1}{n}\),然后随便把剩下的\(n-1\)分配给它的所有子树,记\(1\)的其中一个儿子为\(y\),那么\(y\)选到它所被分配到的数中最小值的概率为\(\frac{1}{siz_{y}}\),然后\(y\)再继续分配给它的子......
  • 关键字和保留字
    关键字定义:是被java赋予了特定含义的英文单词特点:所有字母都小写注意:java中的null不是关键字,和true、false类似,它是一个字面常量,不能作为标识符来进行使用具体可以参考官网:https://docs.oracle.com/javase/tutorial/java/nutsandbolts/_keywords.html初学时并不需要一次性记......
  • python实现ftpServer
    使用python模拟一个fetServer importosimportsocketimportthreadingfrompyftpdlib.authorizersimportDummyAuthorizerfrompyftpdlib.handlersimportFTPHandlerfrompyftpdlib.serversimportFTPServer_source_root=os.path.dirname(os.path.dirname(os.path......
  • python处理process(windows)
    python根据进程名称获取进程id、taskkill进程 importosimportpsutilfrompsutilimportNoSuchProcessclassProcessUtilCls:#停止进程(windows)。#参数:tag=1时按照process_name停止进程,否则按照pids[pid1,pid2...]停止进程@staticmethoddefpr......
  • 国资央企招聘平台的招聘信息爬取
    前言国资央企招聘平台集成了众多国企央企的招聘。写一个脚本实现一下各个岗位的招聘接口当抓包的时候发现,这些岗位信息都是通过接口发布的。因此可以通过获取这个接口的数据爬取。编写代码:'''基于国资央企招聘平台的招聘信息。https://cujiuye.iguopin.com/'''import......
  • 设计模式C++004__装饰器模式
    设计模式C++004__装饰器模式在软件组件设计中,如果职责划分不清晰,使用继承得到的结果往往会随着需求的变化,子类急剧膨胀,同时充斥着重复代码,这时候关键是划清责任。单一职责模式分类中的设计模式:装饰器模式,桥模式1、装饰器模式:动机:在某些情况下,我们可能会“过渡地使用继承来扩......
  • 设计模式C++005__桥模式
    设计模式C++005__桥模式也是组合模式的具体体现。1、动机:由于某些类型的古有的实现逻辑,使得他们具有两个变化的维度,乃至多个维度的变化。?如何应对这种“多维度的变化”,如何利用面向对象技术来使得类型可以轻松地沿着两个乃至多个方向变化,而不引入额外的复杂度。2、桥模式:将......
  • 河南萌新联赛2024第(二)场:南阳理工学院
    1.D-A*BBBB原题链接:https://ac.nowcoder.com/acm/contest/87255/D根据乘法的原理,且b的每一位都相同,最终答案则是错位相加得出的结果,于是我们将a翻转,从个位开始计算,如果当前位置小于a.size就往前累加,但如果大于或等于b.size就从头开始一个一个的减(这个过程可以通过纸上手写乘法计......