责任链模式

 

 责任链模式

目录

 责任链模式

1.什么是责任链模式

2.责任链模式的实现

3.责任链模式的优缺点

4.责任链模式的使用场景

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、可动态指定一组对象处理请求。