责任链模式
责任链模式
目录
1.什么是责任链模式
责任链模式(Chain of Responsibility Pattern)为请求创建了一个接收者对象的链。接收者对象连成一条链条,所有节点具有相似功能,但每个节点所提供的具体功能又有不同的权限。并在该链条上传递请求,直到有一个接收这对象处理它。通过让更多对象有机会处理请求,避免了请求发送者和接收者之间的耦合。
举个例子:
如上图。一个房地产公司,有一线销售人员,有销售经理,大区经理,总监,和CEO。这些职位构成了一条链,用来解决客户的各种要求,从而把房子卖出去。在买卖房子期间,客户会有个很常见的要求,那就是给打个折把,有的要求多,有的要求少。而销售,经理这些职位都会有不同的打折权限,比如销售可以打折5%,而经理可以打折20%,其他职位也类似依次升高。这些人就够成了一条链。当折扣在销售的范围内,销售就给予处理。否则就交给经理,经理处理不了,就再向上传递,交给大区经理,总监,直至CEO。这就是解释了相似的功能,不同的权限。这就是一个很明显的责任链。
再举一个例子:
作为一个Java开发人员,想必在我们的程序中,一定会用到try catch块来处理异常把。这里的catch就是责任链模式。在有多个catch块时,从小范围到大范围,直至有一个catch块处理请求,catch结束。
2.责任链模式的实现
实现原理:
首先,在Handler(解决问题的对象)中聚合自己(包含自己的一个实例,用来指向下一步需那个对象进行处理)。在HandlerRequest方法中,实现具体判断,判断自己是否可以处理该请求,如果可以则返回处理结果,否则将请求传递给下一步的对象进行处理。
以房地产公司例子为例实现代码。
首先,创建PriceHandler抽象类,所有具有相同功能,不同权限的父类。具体请求依赖此类,而不是依赖具体解决问题对象。在此类中,定义具体处理方法processDiscount,来处理请求。具体代码如下:
/**
* protected方便子类访问
* 直接后继,用于传递请求
*/
protected PriceHandler successor;
/**
* 设置后继
* @param successor
*/
public void setSuccessor(PriceHandler successor) {
this.successor = successor;
}
/**
* 处理折扣申请
*/
public abstract void processDiscount(float discount);
其次,PriceHandler的子类,也就是具体的请求处理对象。这里只列出销售人员代码,其他几个职位代码类似,只是权限不同(判断条件不同)。
@Override
public void processDiscount(float discount) {
if (discount <= 0.05) {
System.out.println(this.getClass() + "批准折扣" + discount);
} else {
successor.processDiscount(discount);
}
}
第三,是客户端的代码。Customer类即客户端代码中包含一个PriceHandler,设置交给谁去处理,将请求交给谁。以及请求方法。
private PriceHandler priceHandler;
public void setPriceHandler(PriceHandler priceHandler) {
this.priceHandler = priceHandler;
}
public void requestDiscount(float discount){
priceHandler.processDiscount(discount);
}
最后,完成上述,还需要去完成这些职位的先后顺序,定义处理请求顺序。这里在PriceHandler里定义一个static方法来实现。
public static PriceHandler createPriveHandler() {
PriceHandler sales = new Sales();
PriceHandler man = new Manager();
PriceHandler dir = new Director();
PriceHandler vp = new VicePresident();
PriceHandler ceo = new CEO();
sales.setSuccessor(man);
man.setSuccessor(dir);
dir.setSuccessor(vp);
vp.setSuccessor(ceo);
return sales;
}
至此,责任链的代码基本完成。下面是测试代码及部分运行结果。
public static void main(String[] args) {
Customer customer = new Customer();
customer.setPriceHandler(PriceHandler.createPriveHandler());
Random rand = new Random();
for (int i = 0; i < 100; i++) {
customer.requestDiscount(rand.nextFloat());
}
}
class com.pattern.cor.handler.CEO拒绝折扣0.71930975
class com.pattern.cor.handler.VicePresident批准折扣0.41667616
class com.pattern.cor.handler.CEO批准折扣0.5443123
class com.pattern.cor.handler.CEO拒绝折扣0.8309496
class com.pattern.cor.handler.Director批准折扣0.38392633
class com.pattern.cor.handler.VicePresident批准折扣0.43297845
class com.pattern.cor.handler.CEO拒绝折扣0.57529896
class com.pattern.cor.handler.Director批准折扣0.36871105
class com.pattern.cor.handler.CEO拒绝折扣0.6011103
class com.pattern.cor.handler.VicePresident批准折扣0.4910925
class com.pattern.cor.handler.Manager批准折扣0.064628184
class com.pattern.cor.handler.Manager批准折扣0.16258734
class com.pattern.cor.handler.Manager批准折扣0.28588265
3.责任链模式的优缺点
优点: 1、降低耦合度。它将请求的发送者和接收者解耦。 请求的发送者不用关心具体是谁去解决问题。2、简化了对象。使得对象不需要知道链的结构。 3、增强给对象指派职责的灵活性。通过改变链内的成员或者调动它们的次序,允许动态地新增或者删除责任。 4、增加新的请求处理类很方便。
缺点: 1、不能保证请求一定被接收。 2、系统性能将受到一定影响,而且在进行代码调试时不太方便,可能会造成循环调用。 3、可能不容易观察运行时的特征,有碍于除错。
4.责任链模式的使用场景
1、有多个对象可以处理同一个请求,具体哪个对象处理该请求由运行时刻自动确定。
2、在不明确指定接收者的情况下,向多个对象中的一个提交一个请求。
3、可动态指定一组对象处理请求。