行为型模式

学习笔记之C++设计模式——创建型模式

📑 [【设计模式】[【设计模式】结构型模式|结构型模式

📑 [【设计模式】[【设计模式】创建型模式|创建型模式

总的来说,行为型模式就是用来对类或对象怎样交互和怎样分配职责进行描述。

模板方法模式

模板方法

AbstractClass(抽象类):在抽象类中定义了一系列基本操作(PrimitiveOperations),这些基本操作可以是具体的,也可以是抽象的,每一个基本操作对应算法的一个步骤,在其子类中可以重定义或实现这些步骤。同时,在抽象类中实现了一个模板方法(Template Method),用于定义一个算法的框架,模板方法不仅可以调用在抽象类中实现的基本方法,也可以调用在抽象类的子类中实现的基本方法,还可以调用其他对象中的方法。

ConcreteClass(具体子类):它是抽象类的子类,用于是现在父类中声明的抽象基本操作以完成子类特定算法的步骤,也可以覆盖在父类中的已经实现的具体基本操作。

模板方法案例

模板方法案例

代码

// 模板方法.cpp : 定义控制台应用程序的入口点。
//
 
#include "stdafx.h"
#include <iostream>
#include <string>
using namespace std;
 
// 制作饮料
class Beverage
{
public:
	// 煮水
	void BoilWater() {
		cout << "烧开水" << endl;
	}
	// 冲泡 特殊接口
	virtual void Brew() = 0;
	// 倒入杯中
	void PourinVup() {
		cout << "倒入杯中" << endl;
	}
	// 添加料 特殊接口
	virtual void AddCondiments() = 0;
 
	// Hook 方法,决定某些算法步骤是否挂钩在算法中
	virtual bool CustomWantsCondiments() {
		return true;
	}
 
	// 模板方法
	void PrepareBeverage() {
		BoilWater();
		Brew();
		PourinVup();
		if (CustomWantsCondiments()) {
			AddCondiments();
		}
	}
protected:
	
private:
};
 
class Coffee : public Beverage
{
public:
	virtual void Brew() {
		cout << "冲泡咖啡豆" << endl;
	}
	virtual void AddCondiments() {
		cout << "添加糖和牛奶" << endl;
	}
protected:
private:
};
 
 
class Tea : public Beverage
{
public:
	virtual void Brew() {
		cout << "冲泡茶叶" << endl;
	}
	virtual void AddCondiments() {
		cout << "添加柠檬" << endl;
	}
protected:
private:
};
 
int main()
{
	Beverage *pTea = new Tea;
	pTea->PrepareBeverage();
	delete pTea;
 
	cout << "-----------------------" << endl;
 
	Beverage *pCoffee = new Tea;
	pCoffee->PrepareBeverage();
	delete pCoffee;
 
    return 0;
}

输出:

烧开水
冲泡茶叶
倒入杯中
添加柠檬
-----------------------
烧开水
冲泡茶叶
倒入杯中
添加柠檬
请按任意键继续. . .
## 模板方法的优缺点
  1. 在父类中形式化地定义一个算法,而由它的子类来实现细节的处理,在子类实现详细的处理算法时并不会改变算法中步骤的执行次序。
  2. 模板方法模式是一种代码复用技术,它在类库设计中尤为重要,它提取了类库中的公共行为,将公共行为放在父类中,而通过其子类来实现不同的行为,它鼓励我们恰当使用继承来实现代码复用。
  3. 可实现一种反向控制结构,通过子类覆盖父类的钩子方法来决定某一特定步骤是否需要执行。
  4. 在模板方法模式中可以通过子类来覆盖父类的基本方法,不同的子类可以提供基本方法的不同实现,更换和增加新的子类很方便,符合单一职责原则和开闭原则

需要为每一个基本方法的不同实现提供一个子类,如果父类中可变的基本方法太多,将会导致类的个数增加,系统更加庞大,设计也更加抽象。

适用场景

  1. 具有统一的操作步骤或操作过程;

  2. 具有不同的操作细节;

  3. 存在多个具有同样操作步骤的应用场景,但某些具体的操作细节却各不相同

在抽象类中统一操作步骤,并规定好接口;让子类实现接口。这样可以吧各个具体的子类和操作步骤解耦合。


命令模式

将一个请求封装为一个对象,从而让我们可用不同的请求对客户进行参数化;对请求排队或者记录请求日志,以及支持可撤销的操作。命令模式是一种对象行为模式,其别名为动作(Action)模式或事务(Tranaction)模式。

命令模式可以将请求发送者和接收者完全解耦,发送者与接收者之间没有直接引用关系,发送请求的对象只需要知道如何发送请求,而不必知道如何完成请求。

代码

// 命令模式.cpp : 定义控制台应用程序的入口点。
//
 
#include "stdafx.h"
#include <iostream>
using namespace std;
 
class Doctor
{
public:
	void treat_eye() {
		cout << "医生 治疗 眼科病" << endl;
	}
	void treat_nose() {
		cout << "医生 治疗 鼻科病" << endl;
	}
protected:
private:
};
 
class CommandTreatEye {
public:
	CommandTreatEye(Doctor *doctor) {
		m_doctor = doctor;
	}
 
	void treat() {
		m_doctor->treat_eye();
	}
private:
	Doctor *m_doctor;
};
 
class CommandTreatNose {
public:
	CommandTreatNose(Doctor *doctor) {
		m_doctor = doctor;
	}
 
	void treat() {
		m_doctor->treat_nose();
	}
private:
	Doctor *m_doctor;
};
 
int main()
{
	// 1. 医生直接看病
	Doctor *doctor = new Doctor;
	doctor->treat_eye();
	
	delete doctor;
 
	cout << "-----------------" << endl;
 
	// 2. 通过医疗指令来看病
 
	Doctor *doctorCmd = new Doctor;
	CommandTreatEye * cmdEyeDoc = new CommandTreatEye(doctorCmd);
	cmdEyeDoc->treat();
	delete cmdEyeDoc;
	
	CommandTreatNose *cmdNoseDoc = new CommandTreatNose(doctorCmd);
	cmdNoseDoc->treat();
	delete cmdNoseDoc;
 
	delete doctorCmd;
 
    return 0;
}
 
 

输出:

医生 治疗 眼科病
-----------------
医生 治疗 眼科病
医生 治疗 鼻科病
请按任意键继续. . .
> 命令模式的本质是对请求进行封装对应于一个命令,将发出命令的责任和执行命令的责任分割开。

命令模式中的角色和职责


策略模式


观察者模式