用C++跟你聊聊“职责链模式”

时间:2022-07-23
本文章向大家介绍用C++跟你聊聊“职责链模式”,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

我要请假

那天,咱有点事儿,想请个假。于是和科任老师说了一声,但是科任老师说他这个做不来主,上课离开五分钟还是可以的,但是超过这个时间就要像班主任请示。班主任又说,他的权限只到一早上,像我这样一下子请假一天的,他做不来主,需要向辅导员请示。 就这样绕了一圈,辅导员通过了。

那么这个层层上升的模式,要如何使用代码实现? 用一个switch()?还是用一堆的if···else···? 那如果要对权限进行一波修改呢,班主任只能支持一节课的假,辅导员只能准一上午,要一天就得去找系主任。 这样违反了“单一职责原则”和“开放-封闭原则”。

那怎么办呢?这里推荐“职责链模式”。

其实一开始我不是很喜欢这个东西,感觉没上面用,因为职责需要穷尽。但是后来我转念一想,如果和“桥接模式”组合在一起,那将会有不一样的风景。 这里看“桥接模式

职责链模式

使多个对象都有机会处理请求,从而避免发送者和接收者之间的耦合关系。将这个对象连成一条链,并通过这条链传递该请求,直到有一个对象处理它为止。

小故事代码实现

//抽象管理者
class Manager
{
protected:
	Manager *m_manager;
	string m_name;
public:
	Manager(Manager *manager, string name):m_manager(manager), m_name(name){}
	virtual void DealWithRequest(string name, int num)  {}
};
//科任老师
class CommonManager: public Manager
{
public:
	CommonManager(Manager *manager, string name):Manager(manager,name) {}
	void DealWithRequest(string name, int num) 
	{
		if(num < 1) 
		{
			cout<<"老师"<<m_name<<"批准"<<name<<"请假"<<num<<"节课"<<endl;
		}
		else
		{
			cout<<"老师"<<m_name<<"无法处理,交由班主任处理"<<endl;
			m_manager->DealWithRequest(name, num);
		}
	}
};
//班主任
class Majordomo: public Manager
{
public:
	Majordomo(Manager *manager, string name):Manager(manager,name) {}
	void DealWithRequest(string name, int num) 
	{
		if(num < 4) //班主任职权之内
		{
			cout<<"班主任"<<m_name<<"批准"<<name<<"请假"<<num<<"节课"<<endl<<endl;
		}
		else
		{
			cout<<"班主任"<<m_name<<"无法处理,交由辅导员处理"<<endl;
			m_manager->DealWithRequest(name, num);
		}
	}
};
//辅导员
class GeneralManager: public Manager
{
public:
	GeneralManager(Manager *manager, string name):Manager(manager,name) {}
	void DealWithRequest(string name, int num)  //辅导员可以处理所有请求
	{
		cout<<"辅导员"<<m_name<<"批准"<<name<<"请假"<<num<<"节课"<<endl<<endl;
	}
};

//测试案例
int main()
{	
	Manager *general = new GeneralManager(NULL, "A"); //设置上级,辅导员暂时没有上级
	Manager *majordomo = new Majordomo(general, "B"); //设置上级
	Manager *common = new CommonManager(majordomo, "C"); //设置上级
	common->DealWithRequest("D",1);  
	common->DealWithRequest("E", 3);
	common->DealWithRequest("F", 6);
	delete common; delete majordomo; delete general;
	return 0;
}

职责链的好处

当客户端提交一个请求的时候,请求是沿链传递,直到被处理。 这样就使得接收者和发送者都没有对方的明确信息,且链中对象也不知道链的结构,只能知道他们的上级。 而且可以有链式结构的所有优势。

不过也要当心一个请求一直无法得到处理。

上面的栗子只给出了单一职责,如果要多职责,请自行插入桥接模式。 或者等我下次循环回来的时候写模式混搭的文章,那可能要一个月后了。