责任链模式

初看责任链模式,心里不禁想起了一个以前听过的相声:看牙。说的是一个病人看牙的时候,音声不小心把拔下的牙掉进病人的嗓子里。病人因此楼上楼下的跑了好多可是,最后无果而终。
责任链模式就是这种“推卸”责任的模式,你的问题在我这里能解决我就解决,不行就把你推给另一个对象。至于到底谁解决这个问题,我不管。
Chain of Responsibility 定义
Chain of Responsibility(CoR)是用一系列类(classes)试图处理一个请求request,这些类之间是一个松散的耦合,唯一一个共同点式在他们之间传递request。也就是说,来了一个请求,A类先处理,如果没有处理,就传递到B类处理,如果没有处理就传递到C类处理。就这样象一个链条(Chain)一样传递下去。
避免请求发送者与接受者耦合在一起,让多个对象都有可能接受请求,将这些对象连接成一条连,并且沿着这条链传递请求,直到有对象处理它为止。
二、类与对象的关系
传递着接口(Handler ):定义一个处理请求的接口,(可选)实现链中下一个对象。
具体传递着(Concrete Handler ):处理它所负责的请求,可以访问链中的下一个对象,如果可以处理请求,就处理它,否则将请求转发给后继者。
客户应用程序(Client ):向链中的对象提出最初的请求。
三、范例:1.军队中剧情的传递就是一个责任链,下属行动需要上级比准,所以要把行动计划包给上级,上级有传给上级,直至有一个人可以决定,一个士兵请求进入反恐行动组,他就会给班长发送请求,班长给排长,排长个连长,这样一级一级的传下去,直到传到军长,因为军长能够据顶谁可以参加反恐行动组。
2.既定我们要做一个只能大厦按群系统。安全系统包括很多各种传感器(运动检测器、烟感检测器、温度检测器等),它们的状态会传给计算机。计算机系统的工作是记录这些状态并在紧急事件发生时发出警报。我们设计的系统要有高度可扩展性,它可以适用于小型零售店、办公楼、仓库、多功能大厦等多种场合。
四、优势和缺陷
责任链模式可以减少对象的连接,为对象责任分配增加了很大的灵活性。该模式允许把一组类作为一个类来使用,并且在类的组合中,一个累的时间可以发送到另一个类并有其处理。
责任链模式通常应用于图形用户界面中,窗体的部件可能会包含其他几个小部件,就如同windows窗体应用程序中,控件中又可以防止其他控件,控件编辑诶会决定是否处理事件,或者将时间传递给父控件来处理。
另外,责任链还会以树状出现,这样,一个时间可以传给多个类,或者,多个类的信息可以提交到一个类。树状责任链能够提供更灵活的技巧,但缺点是信息在树中容易迷失。
五、应用情景
超过一个对象能够处理客户请求并且到底哪个对象处理预先不知道。
一个请求可以发布到多个对象但它的接受都是不清晰。
可以动态之地昂一组对象处理请求。
 
六、如何使用
虽然这一段是如何使用CoR,但是也是演示什么是CoR。
有一个Handler接口:

public interface Handler {
public void handleRequest();
}

这是一个处理request的事例,如果有多种request,比如:请求帮助、请求打印、请求格式
最先想到的解决方案就是:在接口中增加多个请求。

public interface Handler {
public void handleHelp();
public void handldPrint();
public void handleFormat();
}

在具体写一段实现Handler代码:

public class ConcreteHandler implements Handler {
private Handler handler ;
 
public ConcreteHandler(Handler handler) {
this . handler = handler;
}
 
public void handleHelp() {
// 具体怎么样去完成帮助
}
 
public void handlePrint() {
// 具体怎么样去完成打印
}
 
public void handleFormat() {
// 具体怎么样去完成格式化
}
}

一共有三个这样的具体实现类,上面是处理help,还有处理Print,处理Format这大概是我们最常用的编程思路。
虽然思路简单明了,但是有一个扩展问题,如果我们需要在增加一个请求request种类,需要修改接口及其每一个实现。
第二种方案:将每种request都变成一个接口,因此我们有以下代码:

public interface HandleHelp {
public void handleHelp();
}
 
public interface HandlePrint {
public void handlePrint();
}
 
public interface HandleFormat {
public void handleFormat();
}

 

public class ConcreteHandler implements HandleHelp, HandlePrint, HandleFormat {
private HandleHelp handleHelp ;
private HandlePrint handlePrint ;
private HandleFormat handleFormat ;
 
public ConcreteHandler(HandleHelp handleHelp, HandlePrint handlePrint,
HandleFormat handleFormat) {
this . handleHelp = handleHelp;
this . handlePrint = handlePrint;
this . handleFormat = handleFormat;
}
 
public void handleHelp() {
// 具体怎么样去完成帮助
}
 
public void handlePrint() {
// 具体怎么样去完成打印
}
 
public void handleFormat() {
// 具体怎么样去完成格式化
}
}

这个方法在增加新的请求request情况下,只是节省了接口的修改量,
接口实现ConcreteHandle还需要修改。而且代码显然不简单美丽。
 
解决方案三:在Handler接口中只使用一个参数化方法:

public interface Handler {
public void handleRequest(String str);
}

那么Handler实现代码如下:

public class ConcreteHandler implements Handler {
private Handler handler;
 
public ConcreteHandler(Handler handler) {
this .handler = handler;
}
 
public void handleRequest(String str) {
if (str.equals( "help" )) {
// 具体完成帮助
} else {
// 传递到下一个类去实现
}
}
}

这个方案是先假设request是String类型,如果不是怎么办?当然我们可以创建一个专门类Request
最后的解决方案:接口Handler的代码如下:

public interface Handler {
public void handleRequest(Request request);
}

Request类的定义如下:

public class Request {
private String str ;
 
public Request(String str) {
this . str = str;
}
 
public String getStr() {
return str ;
}
 
public void executed() {
// 具体的请求
}
}

ConcreteHandler类的定义如下:

public class ConcreteHandler implements Handler {
private Handler handler ;
 
public ConcreteHandler(Handler handler) {
this . handler = handler;
}
 
public void handleRequest(Request request) {
if (request instanceof HelpRequest ) {
// 具体帮助
} else {
request.executed();
// 交给其他的类去实现
}
}
}

这个解决方案就是CoR,在一个链上,都已相应职责的类,因此叫Chain of Responsibility。
七、CoR 的优点
因为无法预知来自外界(客户端)的请求时数以那种类型,每个类如果碰到它不能处理的请求只要放弃就可以。
缺点是效率低,因为一个请求的完成可能要遍历到最后才可能完成,当然也可以用树的概念优化。在java AWT1.1中,对于鼠标按键事件的处理就是使用CoR,到java 1.1后,就是用Observer代替CoR,它的扩展性差,因为在CoR中,一定要有一个统一的接口Handler,局限性就在这里。
八、与Command 模式的区别
Command 模式需要实现协商客户端和服务器端的调用关系,比如1代表Start2代表move等,这些都是封装在Request中,到达服务器端在分解。
CoR模式就无需这种事先约定,服务器端可以使用CoR模式进行客户端请求的猜测,一个一个猜测试验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值