设计模式学习笔记--职责链模式

一.简介

说道职责链模式可能比较陌生,但是我们在工作生活中经常会遇到职责链。比如我最近有事,要请一天的假,那么我在系统上提交一个申请。如果这个假期很短,可能直接上级就批复了。但是如果假期比较长,直接上级没有办法审批,那么这个请求就会继续向上发,转到部门领导。部门领导审批了。而如果假期再长,那么这个请求也许会再上一级。这样的一个过程就是职责链。
看一下职责连模式的定义:在责任链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链。请求在这个链上传递,直到链上的某一个对象决定处理此请求。发出这个请求的客户端并不知道链上的哪一个对象最终处理这个请求,这使得系统可以在不影响客户端的情况下动态地重新组织和分配责任。
职责链模式的UML图:
设计模式学习笔记--职责链模式_第1张图片



二.职责链模式例子

1.没有用职责链,请假的流程

就拿请假的过程来举个例子,我们设计一个简单的请假流程。如果没有用职责链模式时,我们请假就比较繁琐了。写好了假条,先去找组长,组长批不了,那么去找部门领导,还是批不了,那么我们就得拿着假条去找公司领导了。用代码实现如下:
// C++Test.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include 
#include 
using namespace std;

//请求类,有请求内容和参数
class Request
{
private:
	string m_Content;
	int m_Arg;
public:
	Request(string content, int arg)
		:m_Content(content), m_Arg(arg)
	{
		cout<<"生成请求"<
结果:
生成请求
权限不够,请找上级审批
权限不够,请找上级审批
直接找我,还请这么长时间假!你被开了!
完蛋鸟!
请按任意键继续. . .

如果领导审批了最好,如果领导心情不好,你又撞到了枪口上,那么就GG了。

总结一下,这个过程有什么不妥呢?
第一,我们的判断是一个长长的if嵌套,如果还需要增加或者删除审批的中间环节很麻烦,尤其是环节比较多的时候。第二,这样的流程,我们需要和每个级别的领导都进行申请,说的专业一点就是耦合,有些事还是不要掺和的好,万一被开了呢..


2.使用职责链模式,请假的流程

上面那种的请假流程太繁琐,使用职责链模式就可以很好的解决问题。有了职责链,我们只需要提交一个申请,然后这个申请按照公司的流程一级一级自动向上传递,而不是我们自己跑过去找领导,直到被审批为止。然后,我们只需要在提交完申请检查一下申请的结果就好了:
// C++Test.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include 
#include 
#include 
using namespace std;

//请求类,有请求内容和参数
class Request
{
private:
	string m_Content;
	int m_Arg;
	//请求流程的结果
	vector m_Event;
public:
	Request(string content, int arg)
		:m_Content(content), m_Arg(arg)
	{
		cout << "生成请求" << endl;
	}
	//输入结果
	void AddEvent(string event)
	{
		m_Event.push_back(event);
	}

	string GetContent() const { return m_Content; }
	int GetArg()const { return m_Arg; }
	//查看结果
	void ShowResult()
	{
		for (vector::iterator it = m_Event.begin(); it != m_Event.end(); ++it)
		{
			cout << (*it) << endl;;
		}
	}
};

//领导基类
class Manager
{
	//下一个处理者
protected:
	Manager* m_pNext;
public:
	//处理请求
	virtual bool HandleRequest( Request& request) = 0;
	//设置指责链下家
	void SetNextChainNode(Manager* manager)
	{
		m_pNext = manager;
	}
};

//组长
class TeamManager : public Manager
{
public:
	bool HandleRequest(Request& request)
	{
		request.AddEvent("组长审批通过");
		if (request.GetContent() == "leave" && request.GetArg() < 1)
			return true;
		else
		{
			if (m_pNext)
				return m_pNext->HandleRequest(request);
			return false;
		}
	}
};

//部门领导
class DepartmentManager : public Manager
{
public:
	bool HandleRequest(Request& request)
	{
		request.AddEvent("部门领导审批通过");
		if (request.GetContent() == "leave" && request.GetArg() < 1)
			return true;
		else
		{
			if (m_pNext)
				return m_pNext->HandleRequest(request);
			return false;
		}
	}
};

//公司领导
class CompanyManager : public Manager
{
public:
	bool HandleRequest(Request& request)
	{
		if (request.GetContent() == "leave" && request.GetArg() < 10)
		{
			request.AddEvent("公司领导审批通过");
			return true;
		}
		else
		{
			request.AddEvent("请假时间过长,公司领导不予审批");
			return false;
		}
	}
};

//main
int _tmain(int argc, _TCHAR* argv[])
{
	TeamManager teamManager;
	DepartmentManager departmentManager;
	CompanyManager companyManager;

	

	//设置指责链
	teamManager.SetNextChainNode(&departmentManager);
	departmentManager.SetNextChainNode(&companyManager);
	//请求
	Request request("leave", 10);
	//这次,我们只需要给组长交个申请就好了
	teamManager.HandleRequest(request);

	//如今,我们只需要调用申请类的查看结果方法就可以了
	request.ShowResult();



	system("pause");
	return 0;
}
结果:
生成请求
组长审批通过
部门领导审批通过
请假时间过长,公司领导不予审批
请按任意键继续. . .


有了职责链模式,我们只需要在系统初始化的时候,设置好领导们的职责链。然后我们请假就只需要给组长发个申请,如果能批就直接批了,如果批不了,他会自动将申请向他的上级传送,直到审批或者终结为止。这样,整个流程大大的规范化,我们申请也方便得多了。
更重要的是,使用了职责连模式,我们可以很方便的更改申请的流程。比如,我们的审批还需要新增加一个流程,增加一个HR审批,那么,我们只需要重新设置一下职责连的,加入一个HR的处理者,就可以了:
	//新增一个管理者
	HRManager hrManager;

	//重新设置指责链
	teamManager.SetNextChainNode(&departmentManager);
	departmentManager.SetNextChainNode(&hrManager);
	hrManager.SetNextChainNode(&companyManager);
结果:
生成请求
组长审批通过
部门领导审批通过
HR领导审批通过
请假时间过长,公司领导不予审批
请按任意键继续. . .

三.职责链模式的变体

有时候,我们并不是完全要按照设计模式的模式来设计程序,设计模式只是我们编程的一种借鉴思想。我们可以适当更改模式,让我们的程序更加灵活。
职责链模式就很适合修改,纯的职责链模式是要求每个处理者要么处理事务,要么转发事务,并且事务最终必须被处理掉。但是有时候我们的实际情况并不是这样。我们可以让职责链上的每个对象处理事务中的一部分,这样就形成了一个流水线。或者我们可以让事务在这个链上走一圈,链上的每个对象都可以选择是否处理该事务,能处理的处理,不能处理的就转发。总之,模式的死的,但程序是活的,怎么改还是要看需求。

四.职责链模式总结

总结一下职责连模式。
职责链模式的主要优点如下:
1.我们可以把请求和大部分的处理者分离,换句话说我们不需要知道最终处理我们请求的人是谁,只需要知道第一个处理我们请求的人即可。这样大大降低了系统的耦合度。
2.由于职责链模式的灵活性,我们可以很容易的在客户端增加或者删除职责链上的内容,而系统不需要进行修改,符合开放封闭原则。
3.职责链模式很灵活,我们可以衍生出一些变体。而且我们的处理流程也可以不仅仅是链,可以是树,或者环等等。

但是职责链模式也有一些地方需要我们注意:
1.如果职责链变成了环,而且我们没有跳出环的判断的话,就容易变成死循环。而如果链太长,效率也不怎么样。
2.因为是可以在客户端配置职责链的,而客户端有可能不知道具体的对象能处理的流程,那么就可能会造成一个请求在经过整个职责链都没能被处理的情况。


你可能感兴趣的:(设计模式,设计模式学习笔记)