被说了很多遍的设计模式---职责链模式

[把你的理性思维慢慢变成条件反射]

本文,我们讲介绍职责链模式,文章主题结构与上文一致。惯例,先来看看我们示例工程的环境:

操作系统: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);
		}
	}
}	

模式扩展:

“不纯洁”的职责链模式:

在上文所示的概念及示例代码中,我们展示的都是:明确的区别了每一级的职责。即,要么全部处理,要么全部交给下一级处理。

但是,实际上,我们还会遇到需要分级处理的情况,如网络协议的处理过程,每一级都是基于上一级的处理结果,计算当前值,并且将计算结果交给下一级继续处理。这样的处理过程在过滤器中也较为常用。

反思:

应用场景:

  1. 有多个对象可以处理一个请求,但具体交由谁处理,只有在运行时才能确定。
  2. 客户端不关心那个对象最终处理了该对象。但需要一个明确的处理或未出的结果。
  3. 客户端可以任意的指定处理对象层级关系,多个客户端有可能存在不同的处理层级安排。

优点:

  1. 客户端负责创建一个责任链,但丝毫不关心责任链的处理过程。只是期待最终的返回结果。
  2. 每一个对象只建立的向后的连接关系,简化的对象之间的关系设置。
  3. 在一组处理类中,可以存在不同的处理链。
  4. 对于后续新增,修改不必修改服务端,客户端只需重新建立责任链即可,满足了单一职责原则,开闭原则。

缺点:

  1. 一个请求极有可能到了链的末端仍然得不到处理,并且,客户端在最初也不知道当前请求是否一定被处理。
  2. 责任链的长度会对性能产生一定影响。对于测试与调试存在一定障碍。
  3. 需要主要避免死循环。

-------------------------------------------------------------------------------------------------------------------------------------

至此,被说了很多遍的设计模式---职责链模式 结束


参考资料:

图书:《大话设计模式》

其他博文:http://blog.csdn.NET/lovelion/article/details/7563445


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
当代码中的条件语句if-else过于复杂时,可以考虑使用设计模式代替if-else语句,提高代码的可读性和可维护性。以下是一些常见的设计模式,可以用来代替if-else语句: 1. 工厂模式(Factory Pattern):通过工厂方法创建对象,而不是使用条件语句来直接创建对象。这样可以避免在代码中使用大量的if-else语句,同时也可以很方便地添加新的对象类型。 2. 状态模式(State Pattern):将复杂的状态判断逻辑封装到不同的状态类中,避免在代码中使用大量的if-else语句。可以很方便地添加新的状态类型,也可以方便地维护和扩展状态的行为。 3. 策略模式(Strategy Pattern):将不同的算法封装到不同的策略类中,通过选择不同的策略类来实现不同的行为。这样可以避免在代码中使用复杂的if-else语句,同时也可以很方便地添加新的算法类型。 4. 观察者模式(Observer Pattern):将一个对象的状态变化通知给多个观察者对象,避免在代码中使用大量的if-else语句。可以很方便地添加新的观察者对象,也可以方便地维护和扩展观察者的行为。 5. 责任链模式(Chain of Responsibility Pattern):将多个处理对象组成一个链,每个处理对象都可以处理请求,如果一个对象不能处理请求,则将请求传递给下一个处理对象。这样可以避免在代码中使用大量的if-else语句,同时也可以很方便地添加新的处理对象。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值