职责链模式

1.职责链模式是什么

1.百度百科

职责链模式(Chain-of-responsibility pattern) 很多对象由每一个对象对其下家的引用而连接起来形成一条链。请求在这个链上传递,直到链上的某一个对象决定处理此请求。发出这个请求的客户端并不知道链上的哪一个对象最终处理这个请求,这使得系统可以在不影响客户端的情况下动态地重新组织和分配责任。

2.维基百科

In object-oriented design, the chain-of-responsibility pattern is a design pattern consisting of a source of command objects and a series of processing objects.[1] Each processing object contains logic that defines the types of command objects that it can handle; the rest are passed to the next processing object in the chain. A mechanism also exists for adding new processing objects to the end of this chain. Thus, the chain of responsibility is an object oriented version of the if ... else if ... else if ....... else ... endif idiom, with the benefit that the condition–action blocks can be dynamically rearranged and reconfigured at runtime.

3.lz理解

根据运行时间条件,定义一个有责任的接收者对象链,以处理一个请求或将其转发给链上的下一个接收者(如果有的话)。
这使得能够发送一个请求到一个接收者链,而不必知道哪一个处理请求。请求将沿着链传递,直到接收方处理请求。请求的发送者不再耦合到特定的接收者。

4.核心角色

抽象处理者(Handler)角色:定义出一个处理请求的接口。如果需要,接口可以定义 出一个方法以设定和返回对下家的引用。这个角色通常由一个Java抽象类或者Java接口实现。上图中Handler类的聚合关系给出了具体子类对下家的引用,抽象方法handleRequest()规范了子类处理请求的操作。
具体处理者(ConcreteHandler)角色 :具体处理者接到请求后,可以选择将请求处理掉,或者将请求传给下家。由于具体处理者持有对下家的引用,因此,如果需要,具体处理者可以访问下家。

2.职责链模式解决了什么问题

调用封装、解除耦合 职责链模式使得一个对象无须知道是其他哪一个对象处理其请求,对象仅需知道该请求会被处理即可,接收者和发送者都没有对方的明确信息,且链中的对象不需要知道链的结构,由客户端负责链的创建,降低了系统的耦合度。

调用链式处理 请求处理对象仅需维持一个指向其后继者的引用,而不需要维持它对所有的候选处理者的引用,可简化对象的相互连接。

动态增加处理职责 在给对象分派职责时,职责链可以给我们更多的灵活性,可以通过在运行时对该链进行动态的增加或修改来增加或改变处理一个请求的职责。在系统中增加一个新的具体请求处理者时无须修改原有系统的代码,只需要在客户端重新建链即可,从这一点来看是符合“开闭原则”的。

3.职责链模式用法

职责链模式有两种实现方式。一个是完全交由下个领导处理,二是自己处理完后再次交由下级领导处理

1.完全处理

抽象处理类

/**
 * 抽象处理类
 */
public abstract class Handler {
	//上级领导
	protected Handler superiorHandler;

	//处理
	abstract Result processing(Leave leave);

	public void setSuperior(Handler superiorHandler) {
		this.superiorHandler = superiorHandler;
	}
}

用于处理的两个实体对象

//请假条
public class Leave {
	//请假人
	public String name;
	//职位等级
	public int level;
	//请假原因
	public String reason;
	//请假几天
	public int leaveDays;
}

//回应
public class Result {
	//领导是否同意
	public boolean result;
	//批示原因
	public String  msg;

	public Leave leave;
}

具体实现处理类

//主管处理
public class SupervisorHandler extends Handler {

	public final static int SUPERVISOR_LEVEL = 2;

	@Override
	public Result processing(Leave leave) {
		//如果员工级别大于等于自己则交给上级处理
		if(leave.level >= SUPERVISOR_LEVEL) {
			System.out.println("该员工职务级别高于或等于主管级别");
			return superiorHandler.processing(leave);
		}else {
			Result  res = new Result();
			res.result = true;
			res.msg = "主管批准假期";
			res.leave = leave;
			return res;
		}
	}
}

//经理处理
public class ManagerHandler extends Handler {

	public final static int MANAGER_LEVEL = 3;

	@Override
	public Result processing(Leave leave) {
		if (leave.level >= MANAGER_LEVEL) {
			System.out.println("该员工职务级别高于或等于经理级别");
			return superiorHandler.processing(leave);
		} else {
			Result res = new Result();
			res.result = true;
			res.msg = "经理批准假期";
			res.leave = leave;
			return res;
		}
	}
}

//总监处理
public class DirectorHandler extends Handler {

	public final static int DRIECTOR_LEVEL = 4;

	@Override
	public Result processing(Leave leave) {
		if (leave.level >= DRIECTOR_LEVEL) {
			System.out.println("该员工职务级别高于或等于总监级别");
			return superiorHandler.processing(leave);
		} else {
			Result res = new Result();
			res.result = true;
			res.msg = "总监批准假期";
			res.leave = leave;
			return res;
		}
	}

}

//总裁处理
public class PresidentHandler extends Handler {

	public final static int PRESODENT_LEVEL = 5;

	@Override
	public Result processing(Leave leave) {
		if (leave.level >= PRESODENT_LEVEL) {
			System.out.println("该员工职务级别高于或等于总裁级别");
			return superiorHandler.processing(leave);
		} else {
			Result res = new Result();
			res.result = true;
			res.msg = "总裁批准假期";
			res.leave = leave;
			return res;
		}
	}
}

//董事局处理类
public class BoardOfDirectorsHandler extends Handler {

	public final static int BOD_LEVEL = 6;

	@Override
	public Result processing(Leave leave) {
		if (leave.level >= BOD_LEVEL) {
			Result res = new Result();
			res.result = false;
			res.msg = "员工级别错误!";
			res.leave = leave;
			return res;
		} else {
			Result res = new Result();
			res.result = true;
			res.msg = "董事会批准假期";
			res.leave = leave;
			return res;
		}
	}
}

客户端调用

public class Client {
	public static void main(String[] args) {
		//正常情况
		//设置职责链
		SupervisorHandler SupervisorHandler = new SupervisorHandler();
		ManagerHandler ManagerHandler = new ManagerHandler();
		DirectorHandler DirectorHandler = new DirectorHandler();
		PresidentHandler PresidentHandler = new PresidentHandler();
		BoardOfDirectorsHandler BoardOfDirectorsHandler = new BoardOfDirectorsHandler();
		SupervisorHandler.setSuperior(ManagerHandler);
		ManagerHandler.setSuperior(DirectorHandler);
		DirectorHandler.setSuperior(PresidentHandler);
		PresidentHandler.setSuperior(BoardOfDirectorsHandler);
		//总监写了个请假条
		Leave leave = new Leave();
		leave.name="张三";
		leave.level = 5;
		leave.leaveDays = 10;
		leave.reason = "世界那么大,我想去看看";
		Result res = SupervisorHandler.processing(leave);
		System.out.println("姓名:"+res.leave.name+" 职务等级:"+res.leave.level+" 请假"+res.leave.leaveDays+"天。");
		System.out.println("领导"+(res.result ? "同意":"不同意")+"请假请求,原因是:"+res.msg);
	}
}

结果:

该员工职务级别高于或等于主管级别

该员工职务级别高于或等于经理级别

该员工职务级别高于或等于总监级别

该员工职务级别高于或等于总裁级别

姓名:张三 职务等级:5 请假10天。

领导同意请假请求,原因是:董事会批准假期

以上的处理方法还是有些问题的 职责的关联关系暴露在客户端中。这是我们需要将其封装一下对外提供鞥一个统一标准的服务。这是我们建立一个HR部门用来管理调用关系、

管理调用关系的专用类 人力资源部

//人力部门 维护员工关系
public class HumanResourcesDepartment {

	SupervisorHandler SupervisorHandler = new SupervisorHandler();
	ManagerHandler ManagerHandler = new ManagerHandler();
	DirectorHandler DirectorHandler = new DirectorHandler();
	PresidentHandler PresidentHandler = new PresidentHandler();
	BoardOfDirectorsHandler BoardOfDirectorsHandler = new BoardOfDirectorsHandler();

	public Result GoToLeave(Leave leave) {
		SupervisorHandler.setSuperior(ManagerHandler);
		ManagerHandler.setSuperior(DirectorHandler);
		DirectorHandler.setSuperior(PresidentHandler);
		PresidentHandler.setSuperior(BoardOfDirectorsHandler);
		Result res = SupervisorHandler.processing(leave);
		System.out.println("姓名:" + res.leave.name + " 职务等级:" + res.leave.level + " 请假" + res.leave.leaveDays + "天。");
		System.out.println("领导" + (res.result ? "同意" : "不同意") + "请假请求,原因是:" + res.msg);
		return res;
	}
}
//客户调用

public class Client {
	public static void main(String[] args) {

		//写个请假条
		Leave leave = new Leave();
		leave.name="张三";
		leave.level = 5;
		leave.leaveDays = 10;
		leave.reason = "世界那么大,我想去看看";
		//找人力部门请假
		HumanResourcesDepartment hr = new HumanResourcesDepartment();
		hr.GoToLeave(leave);
	}
}

4.职责链模式的问题

调用性能损耗 对于比较长的职责链,请求的处理可能涉及到多个处理对象,系统性能将受到一定影响,而且在进行代码调试时不太方便。

多个职责互相推诿 由于一个请求没有明确的接收者,那么就不能保证它一定会被处理,该请求可能一直到链的末端都得不到处理;一个请求也可能因职责链没有被正确配置而得不到处理。

循环调用 如果建链不当,可能会造成循环调用,将导致系统陷入死循环。

5.职责链模式总结

使用场景:

1.有多个对象可以处理同一个请求,具体哪个对象处理该请求待运行时刻再确定,客户端只需将请求提交到链上,而无须关心请求的处理对象是谁以及它是如何处理的。

2.在不明确指定接收者的情况下,向多个对象中的一个提交一个请求。

3.可动态指定一组对象处理请求,客户端可以动态创建职责链来处理请求,还可以改变链中处理者之间的先后次序。

碎碎念:

职责链模式也是使用很频繁的模式之一,比如java中的多层异常处理、servlet中filter的使用、struts中拦截器的使用。都使用到了职责链模式。在现实生活中很多服务窗口有所谓的一站式服务其实就是将相同的功能通过一个链条串联起来。提供一个标准的处理窗口而不必关心具体是那个handler去处理这个请求。对于调用方和被调用方解除耦合提供了很大的方便。从变化的角度上来讲职责链模式是将所有职责和职责的处理条件封装起来不让外界看到、外界只需知道调用窗口其他不必关心就能完成调用。

引用

http://wiki.jikexueyuan.com/project/design-pattern-behavior/chain-four.html

posted @ 2018-02-07 15:44  枫飘雪落  阅读(253)  评论(0编辑  收藏  举报