[把你的理性思维慢慢变成条件反射]
本文,我们讲介绍职责链模式,文章主题结构与上文一致。惯例,先来看看我们示例工程的环境:
操作系统:win7 x64
其他软件:eclipse mars,jdk8
-------------------------------------------------------------------------------------------------------------------------------------
经典问题:
审批流,权利及方法继承关系处理。
思路分析:
要点一:每一级具有明确的界限的,责任唯一的“权限”。
要点二:责任处理在运行时动态确定。
示例工程:
错误写法:
创建Manager.java文件,具体内容如下:
package com.csdn.ingo.gof_ChainOfResponsibility;
public class Manager {
protected String name;
public Manager(String name) {
this.name = name;
}
public void getResult(String managerLevel, Request request) {
if (managerLevel == "经理") {
if (request.prequestType == "交通费报销单" && request.pnumber <= 2) {
System.out.println("批准:" + name + ",报销金额:" + request.prequestContent);
} else {
System.out.println("无权处理");
}
} else if (managerLevel == "总监") {
if (request.prequestType == "交通费报销单" && request.pnumber < 5) {
System.out.println("批准:" + name + ",报销金额:" + request.prequestContent);
} else {
System.out.println("无权处理");
}
} else if (managerLevel == "总经理") {
if (request.prequestType == "交通费报销单" && request.pnumber < 50) {
System.out.println("批准:" + name + ",报销金额:" + request.prequestContent);
} else if (request.prequestType == "交通费报销单" && request.pnumber > 50) {
System.out.println("超出预算,重新申请");
}
}
}
}
创建Request.java文件,具体内容如下:
package com.csdn.ingo.gof_ChainOfResponsibility;
public class Request {
private String requestType;
public String prequestType;
private String requestContent;
public String prequestContent;
private int number;
public int pnumber;
public String getRequestType() {
return requestType;
}
public void setRequestType(String requestType) {
this.requestType = requestType;
}
public String getRequestContent() {
return requestContent;
}
public void setRequestContent(String requestContent) {
this.requestContent = requestContent;
}
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
}
创建Window.java文件,具体内容如下:
package com.csdn.ingo.gof_ChainOfResponsibility;
public class Window {
public static void main(String[] args) {
Manager jingli = new Manager("经理");
Manager zongjian = new Manager("总监");
Manager zongjingli = new Manager("总经理");
Request request = new Request();
request.prequestType = "交通费报销单";
request.prequestContent="交通费报销单5K元";
request.pnumber = 5;
jingli.getResult("经理", request);
zongjian.getResult("总监", request);
zongjingli.getResult("总经理", request);
}
}
错误原因:
Manager类其违背了单一职责原则,违反了开闭原则,包含过多分支判断,不利于后期扩展。
推荐写法:
创建CommonManager.java文件,具体内容如下:
package com.csdn.ingo.gof_ChainOfResponsibility.two;
public class CommonManager extends Manager{
public CommonManager(String name) {
super(name);
}
@Override
public void requestApplications(Request request) {
if(request.prequestType=="交通费报销单"&&request.pnumber<=2){
System.out.println("批准:"+name+","+request.pnumber);
}else if(superior!=null){
superior.requestApplications(request);
}
}
}
创建GeneralManager.java文件,具体内容如下:
package com.csdn.ingo.gof_ChainOfResponsibility.two;
public class GeneralManager extends Manager {
public GeneralManager(String name) {
super(name);
}
@Override
public void requestApplications(Request request) {
if (request.prequestType == "交通费报销单" && request.pnumber < 50) {
System.out.println("批准:" + name + ",报销金额:" + request.prequestContent);
} else if (request.prequestType == "交通费报销单" && request.pnumber > 50) {
System.out.println("超出预算,重新申请");
} else if (superior != null) {
superior.requestApplications(request);
}
}
}
创建MajorManager.java文件,具体内容如下:
package com.csdn.ingo.gof_ChainOfResponsibility.two;
public class MajorManager extends Manager{
public MajorManager(String name) {
super(name);
}
@Override
public void requestApplications(Request request) {
if(request.prequestType=="交通费报销单"&&request.pnumber<=5){
System.out.println("批准:"+name+","+request.pnumber);
}else if(superior!=null){
superior.requestApplications(request);
}
}
}
创建Manager.java文件,具体内容如下:
package com.csdn.ingo.gof_ChainOfResponsibility.two;
public abstract class Manager {
protected String name;
protected Manager superior;
public Manager(String name){
this.name = name;
}
public void setSuperior(Manager superior){
this.superior = superior;
}
public abstract void requestApplications(Request request);
}
创建Request.java文件,具体内容参考上文。
创建Window.java文件,具体内容如下:
package com.csdn.ingo.gof_ChainOfResponsibility.two;
public class Window {
public static void main(String[] args) {
Manager jingli = new CommonManager("经理");
Manager zongjian = new MajorManager("总监");
Manager zongjingli = new GeneralManager("总经理");
jingli.setSuperior(zongjian);
zongjian.setSuperior(zongjingli);
Request request = new Request();
request.prequestType = "交通费报销单";
request.prequestContent="交通费报销单5K元";
request.pnumber = 5;
jingli.requestApplications(request);
}
}
推荐原因:
- 每一级对象职责明确,能够在运行时动态决定处理请求的等级。
- 类间关系的设计也有利于后期的维护与扩展。
模式总结:
职责链模式结构图:
职责链模式:使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系。将这个对象连成一条链,并沿着这条链传递该请求你,知道有一个对象处理它为止。
组成部分:
Handler(抽象处理类):定义了一个处理请求的接口,一般设计为抽象类。对于其继承类而言,其仍然是一个处理器,因此在抽象类中需要定义一个抽象处理类型的对象(图中的successor),作为对下一级的引用。通过该引用,可以将各个继承类连接为一个责任链结构。
ConcreteHandler(具体处理者类):定义为Handler抽象类的子类,用于实际处理请求。其中需要明确判断当前对象是否拥有处理该请求的权限。
模板代码:
创建ConcreteHandler1.java,ConcreteHandler2.java,ConcreteHandler3.java文件,具体内容如下:(注意区分每一级的if条件变化)
package com.csdn.ingo.gof_ChainOfResponsibility.one;
public class ConcreteHandler1 extends Handler {
@Override
public void HandleRequest(int request) {
if(request>=0&&request<10){
System.out.println(this.getClass().getName()+"处理请求:"+request);
}else if(successor!=null){
successor.HandleRequest(request);
}
}
}
创建Handler.java文件,具体内容如下:
package com.csdn.ingo.gof_ChainOfResponsibility.one;
public abstract class Handler {
protected Handler successor;
public void setSuccesor(Handler successor){
this.successor = successor;
}
public abstract void HandleRequest(int request);
}
创建Window.java文件,具体内容如下:
package com.csdn.ingo.gof_ChainOfResponsibility.one;
public class Window {
public static void main(String[] args) {
Handler h1 = new ConcreteHandler1();
Handler h2 = new ConcreteHandler2();
Handler h3 = new ConcreteHandler3();
h1.setSuccesor(h2);
h2.setSuccesor(h3);
int requests[] ={2,3,13,32,3,21};
for(int i:requests){
h1.HandleRequest(i);
}
}
}
模式扩展:
“不纯洁”的职责链模式:
在上文所示的概念及示例代码中,我们展示的都是:明确的区别了每一级的职责。即,要么全部处理,要么全部交给下一级处理。
但是,实际上,我们还会遇到需要分级处理的情况,如网络协议的处理过程,每一级都是基于上一级的处理结果,计算当前值,并且将计算结果交给下一级继续处理。这样的处理过程在过滤器中也较为常用。
反思:
应用场景:
- 有多个对象可以处理一个请求,但具体交由谁处理,只有在运行时才能确定。
- 客户端不关心那个对象最终处理了该对象。但需要一个明确的处理或未出的结果。
- 客户端可以任意的指定处理对象层级关系,多个客户端有可能存在不同的处理层级安排。
优点:
- 客户端负责创建一个责任链,但丝毫不关心责任链的处理过程。只是期待最终的返回结果。
- 每一个对象只建立的向后的连接关系,简化的对象之间的关系设置。
- 在一组处理类中,可以存在不同的处理链。
- 对于后续新增,修改不必修改服务端,客户端只需重新建立责任链即可,满足了单一职责原则,开闭原则。
缺点:
- 一个请求极有可能到了链的末端仍然得不到处理,并且,客户端在最初也不知道当前请求是否一定被处理。
- 责任链的长度会对性能产生一定影响。对于测试与调试存在一定障碍。
- 需要主要避免死循环。
-------------------------------------------------------------------------------------------------------------------------------------
至此,被说了很多遍的设计模式---职责链模式 结束
参考资料:
图书:《大话设计模式》
其他博文:http://blog.csdn.NET/lovelion/article/details/7563445