Java设计模式之职责链模式

前言

在系统中如果存在多个对象可以处理同一请求,则可以通过职责链模式将这些处理请求的对象连成一条链,让请求沿着该链进行传递。如果链上的对象可以处理该请求则进行处理,否则将请求转发给下家来处理。职责链模式可以将请求的发送者和接收者解耦,客户端无须关心请求的处理细节和传递过程,只需要将请求提交给职责链即可。
在GoF设计模式中包含11种行为型设计模式,它们的名称、定义整理如下:

模式名称定义
职责链模式(Chain of Responsibility Pattern)避免将一个请求的发送者与接收者耦合在一起,让多个对象都有机会处理请求。将接收请求的对象连接成一条链,并且沿着这条链传递请求,直到有一个对象能够处理它为止。
命令模式(Command Pattern)将一个请求封装成一个对象,从而可用不同的请求对客户进行参数化,对请求排队或者记录请求日志,以及支持可撤销的操作
解释器模式(Interpreter Pattern)给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子
迭代器模式(Iterator Pattern)提供一种方法顺序访问一个聚合对象中的各个元素,而又不用暴露该对象的内部表示
中介者模式(Mediator Pattern)定义一个对象来封装一系列对象的交互。中介者模式使各对象之间不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互
备忘录模式(Memento Pattern)在不破坏封装的前提下捕获一个对象的内部状态,并在该对象之外保存这个状态,这样可以在以后将对象恢复到原先保存的状态
观察者模式(Observer Pattern)定义对象之间的一种一对多依赖关系,使得每当一个对象状态发生改变时其相关依赖对象皆得到通知并被自动更新
状态模式(State Pattern)允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类
策略模式(Strategy Pattern)定义一系列算法,将每一个算法封装起来,并让它们可以相互替换,策略模式让算法可以独立于使用它的客户而变化
模板方法模式(Template Method Pattern)定义一个操作中算法的框架,而将一些步骤延迟到子类中。模板方法模式使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤
访问者模式(Visitor Pattern)表示一个作用于某对象结构中的各个元素的操作。访问者模式让用户可以在不改变各元素的类的前提下定义作用于这些元素的新操作

正文

职责链可以是一条直线、一个环或者一个树形结构,最常见的职责链是直线型,即沿着一条单向的链来传递请求。链上的每一个对象都是请求处理者,职责链模式可以将请求的处理者组织成一条链,并让请求沿着链传递,由链上的处理者对请求进行相应的处理,客户端无须关心请求的处理细节以及请求的传递,只需将请求发送到链上即可,将请求的发送者和请求的处理者解耦。这就是职责链模式的模式动机。

一、定义

定义如下:

职责链模式: 避免将一个请求的发送者与接收者耦合在一起,让多个对象都有机会处理请求。将接收请求的对象
连接成一条链,并且沿着这条链传递请求,直到有一个对象能够处理它为止。
Chain of Responsibility Pattern: Avoid coupling the sender of a request to its receiver
by giving more than one object a chance to handle the request.Chain the receiving
objects and pass the request along the chain until an object handles it.

职责链模式又称责任链模式,它是一种对象行为型模式。

二、结构

职责链模式包含2个角色:
(1)Handler(抽象处理器):它定义了一个处理请求的接口,一般设计为抽象类,由于不同的具体处理器处理请求的方式不同,因此在其中定义了抽象请求处理方法。每一个处理者的下家还是一个处理者,故在处理者中定义了一个抽象处理者类型的对象作为其对下家的引用,通过该引用处理者可以连成一条链。
(2)ConcreteHandler(具体处理者):它是抽象处理者的子类,可以处理用户请求,在具体处理者类中实现了抽象请求处理方法,在处理请求之前需要进行判断,看是否有相应的处理权限,如果可以处理请求就处理它,否则将请求转发给后继者;在具体处理者中可以访问链中的下一个对象,以便请求的转发。

三、实现

职责链模式的核心在于抽象处理者类的设计,抽象处理者的典型代码如下:

public abstract class Handler{
	//维持对下家的引用
	protected Handler successor;

	public void setSuccessor(Handler successor){
		this.successor = successor;
	}
	
	public abstract void handleRequest(String request);
}

具体处理者类的典型代码如下:

public class ConcreteHandler extends Handler{
	public void handleRequest(String request){
		if(请求满足条件){
			//处理条件
		}
		else{
			this.successor.handleRequest(request);	//转发请求
		}
	}
}

需要注意的是,职责链模式并不负责创建职责链,职责链的创建工作必须由系统的其他部分来完成。
典型的客户端代码如下:

Handler handler1,handler2,handler3;
handler1 = new ConcreteHandlerA();
handler2 = new ConcreteHandlerB();
handler3 = new ConcreteHandlerC();
// 创建职责链
handler1.setSuccessor(handler2);
handler2.setSuccessor(handler3);
// 发送请求,请求对象通常为自定义类型
handler1.handleRequest("请求对象");

四、纯与不纯的职责链模式

1、纯的职责链模式

一个纯的职责链模式要求一个具体处理者对象只能在两个行为中选择一个,要么承担全部责任,要么将责任推给下家,不允许出现某一个具体处理者对象在承担了一部分或者全部责任后又将责任向下传递的情况。而且在纯的职责链模式中要求一个请求必须被某个处理者对象处理的情况。

2、不纯的职责链模式

在一个不纯的职责链模式中允许某个请求被一个具体处理者部分处理后再向下传递,或者一个具体处理者处理完某请求后,其后继处理者可以继续处理该请求,而且一个请求可以最终不被任何处理者对象所接收并处理。

在Java AWT 1.0中的事件处理模型里应用了不纯的职责链模式,Java 1.1以后,JDK便采用观察者模式来处理事件。

五、职责链模式优缺点与适用环境

优点

(1)职责链模式使得一个对象无须知道是其他哪一个对象处理其请求,对象仅需知道该请求会被处理即可,接收者和发送者都没有对方的明确信息,并且链中的对象不需要知道链的结构,由客户端负责链的创建,降低了系统的耦合度。
(2)请求处理对象仅需维持一个指向其后继者的引用,而不需要维持它对所有的候选处理者的引用,可简化对象之间的相互连接。
(3)在给对象分派职责时,职责链可以带来更多的灵活性,可以通过在运行时对该链进行动态的增加或修改来增加或改变处理一个请求的职责。
(4)在系统中增加一个新的具体请求处理者时无须修改原有系统的代码,只需要在客户端重新建链即可,从这一点来看是符合开闭原则的。

缺点

(1)由于一个请求没有明确的接收者,那么就不能保证它一定会被处理,该请求可能一直到链的末端都得不到处理;一个请求也可能因职责链没有被正确配置而得不到处理。
(2)对于比较长的职责链,请求的处理可能涉及多个处理对象,系统性能将受到一定的影响,而且在进行代码调试时不太方便。
(3)如果建链不当,可能会造成循环调用,将导致系统陷入死循环。

适用环境

(1)有多个对象可以处理同一请求,具体哪个对象处理该请求待运行时再确定,客户端只需将请求提交到链上,而无须关心请求的处理对象是谁以及它是如何处理的。
(2)在不明确指定接收者的情况下向多个对象中的一个提交一个请求。
(3)可动态指定一组对象处理请求,客户端可以动态创建职责链来处理请求,还可以改变链中处理者之间的先后次序。

以上文字,大量摘抄自《Java设计模式》一书,由刘伟老师编著,故本文应当列入转载一类,有兴趣的朋友可以直接阅读原书。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值