[设计模式]ChainOfResponsibility责任链模式

顾名思义,责任链模式是一条链,链上有多个节点,每个节点都有各自的责任。当有输入时,第一个责任节点看自己能否处理该输入,如果可以就处理。如果不能就交由下一个责任节点处理。依次类推,直到最后一个责任节点。

问题

熟悉VC/MFC的都知道,vc是”基于消息,事件驱动”,消息在vc开发中起着举足轻重的作用。在MFC中,消息是通过一个向上递交的方式进行处理,例如一个WM_Command消息的查出来流程可能为

  • 1)MDI主窗口收到命令消息WM_Command,其ID位ID_XXX
  • 2)MDI主窗口将消息传给当前活动的MDI子窗口
  • 3)MDI子窗口给自己的子窗口(View)一个处理机会,将消息交给View
  • 4)View检查自己MessageMap
  • 5)如果View没有发现处理该消息的程序,则将该消息传其对应的Document对象;否则View处理,消息流程结束
  • 6)Document检查自己MessageMap,如果没有该消息的处理程序,则该消息传给其对象的DocumentTemplate处理,否则自己处理,消息流程结束
  • 7)如果在6)中消息没有得到处理,则将消息返回给view
  • 8)View再传回给MDI子窗口
  • 9)MID子窗口将该消息传给CwinApp对象,CwinApp为所有无主的消息提供了处理

MFC提供了消息的处理的链式处理策略,处理消息的请求将沿着预先定义好的路径依次进行处理。消息的发送者并不知道该消息最后是由哪个具体对象处理的,当然它也无须也不想知道,但是结果是该消息被某个对象处理了,或者一直到一个终极的对象进行处理了。

普通员工发起一个请假申请,当请假天数小于3天时只需要得到主管批准即可;当请假天数大于3天时,主管批准后还需要提交给经理审批,经理审批通过,若请假天数大于7天还需要进一步提交给总经理审批。

ChainOfResponsibility模式描述其实就是这样一类问题将可能处理一个请求的对象链接成一个链,并将请求在这个链上传递,直到对象处理该请求。

ChainOfResponsibility

使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它。 顾名思义,责任链模式为请求创建了一个接收者对象的链。对请求的发送者和接收者进行解耦

抽象处理者(Handler)角色:定义出一个处理请求的接口。如果需要,接口可以定义出一个方法以设定和返回对下家的引用。因此抽象处理者本身还包含了一个本身的引用( successor)作为其对下家的引用,以便将处理者链成一条链;
具体处理者(ConcreteHandler)角色:具体处理者接到请求后,可以选择将请求处理掉,或者将请求传给下家。由于具体处理者持有对下家的引用,因此,如果需要,具体处理者可以访问下家。

  • 关键代码:Handler里面聚合它自己,在 HandlerRequest 里判断是否合适,如果没达到条件则向下传递,向谁传递之前先 set 进去。
  • 优点: 降低耦合度。它将请求的发送者和接收者解耦。
  • 使用场景: 有多个对象可以处理同一个请求,具体哪个对象处理该请求由运行时刻自动确定;需要动态指定处理者的时候
  • 适用于:链条式处理事情。工作流程化、消息处理流程化、事物流程化;
  • 应用实例: 1、红楼梦中的"击鼓传花"。 2、JS 中的事件冒泡
  • 缺点:因为对象不知道是其它哪一个对象处理其请求的,所以职责链模式不保证对象被接收。

     

对责任链的理解,关键在于对链的理解,即包含如下两点:

  • 链是一系列节点的集合,在责任链中,节点实质上是指请求的处理者;

  • 链的各节点可灵活拆分再重组,在责任链中,实质上就是请求发送者与请求处理者的解耦。

小demo

chainOfResponsibility.h

#ifndef CHAINOFRESPONSIBILITY_H
#define CHAINOFRESPONSIBILITY_H

#include <stdio.h>

// 抽象基类,定义一个处理请求的接口
class Handler
{
public:
	Handler(Handler *pSuccessor = NULL);//设置参数,下一个待处理者,可以形成链
        //构造函数中传参,也可以改赵成一个独立的函数
        void setHandlerSuccessor(Handler *pSuccessor = NULL)
        {
            m_pSuccessor = pSuccessor;
        }

	virtual ~Handler();

	// 纯虚函数,由派生类实现
	virtual void HandleRequset() = 0;
protected:
	Handler* m_pSuccessor;
};

class ConcreateHandler1 : public Handler
{
public:
	ConcreateHandler1(Handler *pSuccessor = NULL) : Handler(pSuccessor){}
	virtual ~ConcreateHandler1(){}

	virtual void HandleRequset();
};

class ConcreateHandler2 : public Handler
{
public:
	ConcreateHandler2(Handler *pSuccessor = NULL) : Handler(pSuccessor){}
	virtual ~ConcreateHandler2(){}

	virtual void HandleRequset();
};

#endif

chainOfResponsibility.cpp

#include "ChainOfResponsibility.h"
#include <iostream>

Handler::Handler(Handler *pSuccessor /* = NULL*/) 	: m_pSuccessor(pSuccessor)
{
}

Handler::~Handler()
{
	delete m_pSuccessor;
	m_pSuccessor = NULL;
}

void ConcreateHandler1::HandleRequset()
{
	if (NULL != m_pSuccessor)
	{
		m_pSuccessor->HandleRequset();
		std::cout << "ConcreateHandler1::HandleRequset()\n";
	}
	else
	{
		std::cout << "HandleRequset by ConcreateHandler1\n";
	}
}

void ConcreateHandler2::HandleRequset()
{
	if (NULL != m_pSuccessor)
	{
		m_pSuccessor->HandleRequset();
		std::cout << "ConcreateHandler2::HandleRequset()\n";
	}
	else
	{
		std::cout << "HandleRequset by ConcreateHandler2\n";
	}
}

main.cpp

#include "ChainOfResponsibility.h"
#include <stdlib.h>

int main()
{
	Handler *p1 = new ConcreateHandler1();
	Handler *p2 = new ConcreateHandler2(p1);
	p2->HandleRequset();

	p1->HandleRequset();//没有后继对象,就得自己处理了
        
        // p1->setHandlerSuccessor(p2);//可以让用户来自己设置
	delete p2;
	system("pause");
	return 0;
}

输出结果:

ChainOfResponsibility模式的最大的一个特点就是给系统降低了耦合性,请求的发送者完全不必知道该请求会被哪个应答对象处理,极大地降低了系统的耦合性。

纯与不纯的责任链模式

纯的责任链模式

  • 一个具体处理者对象只能在两个行为中选择一个:要么承担全部责任,要么将责任推给下家,不允许出现某一个具体处理者对象在承担了一部分或全部责任后 又将责任向下传递的情况
  • 一个请求必须被某一个处理者对象所接收,不能出现某个请求未被任何一个处理者对象处理的情况

不纯的责任链模式

  • 允许某个请求被一个具体处理者部分处理后再向下传递
  • 或者一个具体处理者处理完某请求后其后继处理者可以继续处理该请求
  • 而且一个请求可以最终不被任何处理者对象所接收

设计模式|责任链模式及典型应用          责任链模式-网络请求

与其他模式的关系

责任链模式、命令模式、中介者模式和观察者模式用于处理请求发送者和接收者之间的不同连接方式:

  • 责任链按照顺序将请求动态传递给一系列的潜在接收者,直至其中一名接收者对请求进行处理。
  • 命令在发送者和请求者之间建立单向连接。
  • 中介者清除了发送者和请求者之间的直接连接,强制它们通过一个中介对象进行间接沟通。
  • 观察者允许接收者动态地订阅或取消接收请求。

责任链通常和组合模式结合使用。在这种情况下,叶组件接收到请求后, 可以将请求沿包含全体父组件的链一直传递至对象树的底部。

责任链的管理者可使用命令模式实现。在这种情况下,你可以对由请求代表的同一个上下文对象执行许多不同的操作。还有另外一种实现方式,那就是请求自身就是一个命令对象。 在这种情况下, 你可以对由一系列不同上下文连接而成的链执行相同的操作。

责任链和装饰模式的类结构非常相似。两者都依赖递归组合将需要执行的操作传递给一系列对象。但是,两者有几点重要的不同之处。责任链的管理者可以相互独立地执行一切操作,还可以随时停止传递请求。另一方面,各种装饰可以在遵循基本接口的情况下扩展对象的行为。 此外,装饰无法中断请求的传递。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值