Java模式之责任链模式

从请假开始谈起

话说上次五一请假回去玩了一个多星期,期间回了一次老家,去了一趟武汉,接着又跑到了景德镇,和庐山;玩的好不自在;但是想起来上次请假的经历另我记忆犹新啊,算起来也是一波三折吧;

记得那时是4月20号,因为家里出了点事情,急需回家,然后也快到五一了,就想出去玩几天,因为之前加班积攒了不少的调休,所以想把调休给用了。记得当时我是先跟我们的部门经理说,我们部门经理跟我关系比较好,我就说胡哥,我想请假,回家有点事情,随便出去玩几天,胡哥说没问题啊,随便请。然后问我请几天,我说八天。胡哥说:“八天不行啊,你要是请一天,我还能满足你,但是一天以上的你就得找我们的老大,部门总监王总了!”,我说那我去找一下王总吧,王总说,你要请八天假啊,这个我是同意的,但是我只能处理三天内的假期,然后对我说,这事你得去找一下人事部门的老大让他给你签字,然后我找到了张总,张总说请假,没问题啊,先填写请假单吧,填完了请假单之后,张总一看,嗯,没问题,不过你这个已经超过了一个星期了,你得CEO申请一下。最后我又找到了CEO,然后CEO说了一番鼓励我的话,叫我处理完事情之后早点来上班;整个请假算是告一段落了;

在阎宏博士的《Java与模式》一书中开头是这样描述责任链(Chain of Responsibility)模式的:

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


责任链模式的结构

  下面使用了一个责任链模式的最简单的实现。

  责任链模式涉及到的角色如下所示:

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

  ●  具体处理者(ConcreteHandler)角色:具体处理者接到请求后,可以选择将请求处理掉,或者将请求传给下家。由于具体处理者持有对下家的引用,因此,如果需要,具体处理者可以访问下家。


什么是链:

上面讲到了我请假的流程和责任链模式的一种介绍,那么我们可以理解一下,什么是链;

1. 链是多个节点的有序集合。

2. 链的各节点可灵活拆分再重组。

再谈请假:

先创建一个Handler用来处理我们的请假流程

/*
 * 处理人,负责处理请假申请
 */
public abstract class LeaveHandler {
	/*
	 * 直接后继,用于传递请求
	 */
	protected LeaveHandler successor;

	public void setSuccessor(LeaveHandler successor) {
		this.successor = successor;
	}

	/*
	 * 处理请假申请
	 */
	public abstract void disposeLeave(int day);
}
好了现在创建我们的项目经理,他只能够处理一天的假期;如果超过了一天我们就要向他的上级传递请求

/*
 * 项目经理可以批准一天的假期
 */
public class Lead extends LeaveHandler {

	@Override
	public void disposeLeave(int day) {
		if (day <=  1) {
			System.out.println("我叫做胡经理,我可以处理" + day + "的假期");
		} else {
			// 如果他处理不了就向上传递请求
			successor.disposeLeave(day);
		}

	}

}

/*
 * 技术总监可以批准三天的假期
 */
public class CTO extends LeaveHandler{
	@Override
	public void disposeLeave(int day) {
		if (day <= 3) {
			System.out.println("我叫做王总监,我可以处理" + day + "内的假期");
		} else {
			// 如果他处理不了就向上传递请求
			successor.disposeLeave(day);
		}

	}

}

/*
 * 人事部门老大可以批准一个星期内的假期
 */
public class HrBoos extends LeaveHandler{
	@Override
	public void disposeLeave(int day) {
		if (day <= 5) {
			System.out.println("我叫做张老大,我可以处理" + day + "内的假期");
		} else {
			// 如果他处理不了就向上传递请求
			successor.disposeLeave(day);
		}

	}

}

/*
 * 老板,只要他同意,你可以无限期休假
 */
public class CEO extends LeaveHandler {
	@Override
	public void disposeLeave(int day) {
		//因为这里所有的假期他都可以处理所以没有判断
	System.out.println("我叫做CEO,我可以处理" + day + "的假期");
	}

}

public class LeaveHandlerFactory {
	
	
	/*/
	 * 创建工厂方法
	 */
	public static LeaveHandler createHandler(){
		LeaveHandler lead=new Lead();
		LeaveHandler cto=new CTO();
		LeaveHandler hrBoos=new HrBoos();
		LeaveHandler ceo=new CEO();
		
		lead.setSuccessor(cto);
		cto.setSuccessor(hrBoos);
		hrBoos.setSuccessor(ceo);
		return lead;
	}

最后编写测试用例

public class Test {
	private LeaveHandler handler;
	
	public LeaveHandler getHandler() {
		return handler;
	}

	public void setHandler(LeaveHandler handler) {
		this.handler = handler;
	}
	public void requestDiscount(int day){
		handler.disposeLeave(day);
	}
	

	public static void main(String[] args) {
		Test test=new Test();
		test.setHandler(LeaveHandlerFactory.createHandler());
		test.requestDiscount(8);
		
	}

}

责任链模式的优缺点:

模式的有点就在于实现了解耦,符合开闭原则,在这里面调用者不需要知道具体的传递过程,他只需要知道最终的结果被处理了。而且这个链表的结构可以被灵活的更改重组。

但是它的缺点也是很明显的,首先从性能上说起,一个是调用时间,如果链表在最开始被处理了还好,万一链表跑到了最后一个才被处理,那么他的调用时间肯定会比不适用责任链模式的效率要低一些;第二是内存的问题,我们会构造出很多的链表节点对象,但是有些对象在我们的应用场景中是不会用到的,所以大大的消耗了我们的内存;

纯的与不纯的责任链模式
  一个纯的责任链模式要求一个具体的处理者对象只能在两个行为中选择一个:一是承担责任,而是把责任推给下家。不允许出现某一个具体处理者对象在承担了一部分责任后又 把责任向下传的情况。
  在一个纯的责任链模式里面,一个请求必须被某一个处理者对象所接收;在一个不纯的责任链模式里面,一个请求可以最终不被任何接收端对象所接收。
  纯的责任链模式的实际例子很难找到,一般看到的例子均是不纯的责任链模式的实现。有些人认为不纯的责任链根本不是责任链模式,这也许是有道理的。但是在实际的系统里,纯的责任链很难找到。如果坚持责任链不纯便不是责任链模式,那么责任链模式便不会有太大意义了。
我们经常用到的责任链模式:

在早期的java中使用到责任链的有AWT这个项目;


后来改为了观察者模式,我想这也是性能的问题;

还有我们的



异常处理机制,我们捕获了一个异常之后可以选择自己去处理掉这个异常,也可以选择往上抛出异常;

还有前端的


DOM树也是一样,当我们对TD绑定了一个点击事件并且触发之后,它会从这个document去寻找,如果没有找到就接着往下找,直到找到了这个TD,再返回这个点击事件;

当然还有我们比较熟悉的Filter过滤器

public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {
        
        chain.doFilter(request, response);
    }

    public void destroy() {
    }

    public void init(FilterConfig filterConfig) throws ServletException {
    }

它可以自己去处理这个请求,也可以交给下一个拦截器去处理;

职责链总结

职责链模式不能乱用,否则非常容易变成因为模式而模式的反例。

如果有更好的模式可以代替我们的责任链模式的话,可以考虑去替代它。


  • 7
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
责任链模式是一种行为设计模式,用于解耦发送请求者和处理请求者之间的关系。在责任链模式中,多个对象组成一条链,每个对象都有机会处理请求,如果一个对象不能处理该请求,则将该请求传递给下一个对象。该模式允许请求在链中的不同对象之间传递,直到找到一个能够处理该请求的对象为止。 在Java中实现责任链模式的一种方法是使用一个基类接口定义处理请求的方法,然后每个具体的处理者都实现这个接口。接口中可以定义一个指向下一个处理者的引用,以便处理者可以将请求传递给下一个对象。 下面是一个使用Java实现责任链模式的示例: ```java // 定义一个处理请求的接口 interface Handler { void handleRequest(Request request); } // 具体的处理者类 class ConcreteHandler1 implements Handler { private Handler nextHandler; @Override public void handleRequest(Request request) { // 如果满足处理条件,则处理该请求,否则将请求传递给下一个处理者 if (request.getCondition()) { // 处理请求的代码 } else { nextHandler.handleRequest(request); } } // 设置下一个处理者 public void setNextHandler(Handler nextHandler) { this.nextHandler = nextHandler; } } class ConcreteHandler2 implements Handler { private Handler nextHandler; @Override public void handleRequest(Request request) { // 如果满足处理条件,则处理该请求,否则将请求传递给下一个处理者 if (request.getCondition()) { // 处理请求的代码 } else { nextHandler.handleRequest(request); } } // 设置下一个处理者 public void setNextHandler(Handler nextHandler) { this.nextHandler = nextHandler; } } // 请求类 class Request { private boolean condition; public boolean getCondition() { return condition; } } public class Main { public static void main(String[] args) { // 创建责任链 Handler handler1 = new ConcreteHandler1(); Handler handler2 = new ConcreteHandler2(); handler1.setNextHandler(handler2); // 创建请求 Request request = new Request(); // 处理请求 handler1.handleRequest(request); } } ``` 在上面的示例中,我们定义了一个处理请求的接口`Handler`,并实现了两个具体的处理者类`ConcreteHandler1`和`ConcreteHandler2`。在`handleRequest`方法中,我们首先判断是否满足处理条件,如果满足则处理请求,否则将请求传递给下一个处理者。 在`Main`类中,我们创建了一个责任链,并设置了处理者的顺序。然后创建一个请求对象,并调用`handleRequest`方法开始处理请求。请求会沿着责任链依次传递,直到找到能够处理该请求的处理者为止。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值