设计模式:职责链模式 C++实现


前言

今天复习了下职责链模式,并用c++实现了该模式的一个简单例子。


1. 职责链模式理解

职责链模式,顾名思义,不同职责由不同对象来完成,这些对象连成一条链,按照这条链来处理请求。看完该模式后,第一个想法就是可以用它改善冗长的if…else if … else语句,该模式满足单一职责原则与开放-封闭原则。

职责链模式比较正规的定义与类图结构(引用《大话设计模式》)如下所示:
在这里插入图片描述
在这里插入图片描述
从类图可以看出,该模式应用了类的多态技术:分别定义抽象类和具体类,具体类覆盖实现抽象类的抽象方法;在Handler类中组合该类的对象,实现当前类无法处理时交给下一级继续处理,这也是职责链模式的魅力所在。

职责链模式中组合关系的用法和装饰者模式有异曲同工之妙。


2. C++实现职责链模式

这里以公司中员工申请加薪,请假,。。。为例实现职责链模式的应用,具体类图(引用《大话设计模式》如下所示:
在这里插入图片描述
代码实现如下:

#include <iostream>
#include <memory>

//*****************************Chain Of Responsibility Pattern**************************
//定义请求类
struct Request
{
	std::string requestType;//请求类型
	int			number;//该请求类型的数量
	std::string requestContent;//请求内容
};

//定义抽象经理类
class Manager
{
private:
	std::string name;
	std::shared_ptr<Manager> superior;

public:
	Manager(const std::string& strName): name(strName){}

	void SetSuperior(std::shared_ptr<Manager> smartSuperior)
	{
		superior = smartSuperior;
	}

	std::shared_ptr<Manager> GetSuperior() const
	{
		return superior;
	}

	const std::string& GetName() const
	{
		return name;
	}

	virtual void RequestApplications(const Request& request) = 0;
};

//定义经理类
class CommonManager : public Manager
{
public:
	CommonManager(const std::string& strName): Manager(strName){}
	virtual void RequestApplications(const Request& request)
	{
		if (request.requestType == "请假" && request.number <= 2)
		{
			std::cout << "" << GetName().c_str() << ":" << request.requestContent.c_str() << " 数量 " << request.number << " 被批准!" << std::endl;
		}
		else
		{
			std::shared_ptr<Manager> superior = GetSuperior();
			if (superior != NULL)
			{
				superior->RequestApplications(request);
			}
		}
	}
};

//定义总监类
class Majordomo : public Manager
{
public:
	Majordomo(const std::string& strName) : Manager(strName) {}
	virtual void RequestApplications(const Request& request)
	{
		if (request.requestType == "请假" && request.number <= 5)
		{
			std::cout << "" << GetName().c_str() << ":" << request.requestContent.c_str() << " 数量 " << request.number << " 被批准!" << std::endl;
		}
		else
		{
			std::shared_ptr<Manager> superior = GetSuperior();
			if (superior != NULL)
			{
				superior->RequestApplications(request);
			}
		}
	}
};

//定义总经理类
class GeneralManager : public Manager
{
public:
	GeneralManager(const std::string& strName) : Manager(strName) {}
	virtual void RequestApplications(const Request& request)
	{
		if (request.requestType == "请假" || 
			(request.requestType == "加薪" && request.number <= 500))
		{
			std::cout << "" << GetName().c_str() << ":" << request.requestContent.c_str() << " 数量 " << request.number << " 被批准!" << std::endl;
		}
		else if (request.requestType == "加薪" && request.number > 500)
		{
			std::cout << "" << GetName().c_str() << ":" << request.requestContent.c_str() << " 数量 " << request.number << " 拒绝!" << std::endl;
		}
		else
		{
			std::cout << "" << GetName().c_str() << ":" << request.requestContent.c_str() << " 数量 " << request.number << " 无法处理!" << std::endl;
		}
	}
};


//****************************Test*******************************
int main()
{
	std::shared_ptr<Manager> manager = std::make_shared<CommonManager>("经理");
	std::shared_ptr<Manager> major = std::make_shared<Majordomo>("总监");
	std::shared_ptr<Manager> generalManager = std::make_shared<GeneralManager>("总经理");

	manager->SetSuperior(major);
	major->SetSuperior(generalManager);

	std::cout << "员工申请请假结果:" << std::endl;
	Request request;
	request.requestType = "请假";
	request.number = 1;
	request.requestContent = "小菜请假";
	manager->RequestApplications(request);

	std::cout << std::endl << "员工申请加薪结果:" << std::endl;
	request.requestType = "加薪";
	request.number = 400;
	request.requestContent = "小菜加薪";
	manager->RequestApplications(request);

	system("pause");
	return 0;
}

总结

职责链模式个人应用的比较少,但是觉得很有用,至少对于处理复杂的分支问题时可以考虑使用它增加代码的可维护性、拓展性,但是要注意,请求可能最后无法被处理,这要根据具体应用场景事先考虑全面。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值