设计模式之责任链

责任链模式

简介

GoF分类:行为型设计模式。

英文名:Chain of Responsibility。

管道模式:责任链模式的常用变种之一,纯的责任链模式在链上只会有一个处理器用于处理数据,而管道模式上多个处理器都会处理数据。

应用场景1:Netty、Spring MVC、Selvlet等组件或者框架的拦截器部分都应用了责任链模式。

应用场景2:当你的调用链太长,或者有异步代码嵌套太深,可以考虑用责任链模式优化代码。

示例1-递归调用

示例1:以下代码来源自《图解设计模式》中的示例,模拟的是问题处理过程。

package com.wwq.ChainResponsibility.tj;

import com.wwq.ChainResponsibility.tj.bean.Trouble;

/**
 * 
 * @ClassName: Support
 * @Description: 解决问题的抽象类
 * @author: 王同学
 * @date: 2023年5月8日 下午3:52:18
 * @Copyright:
 */
public abstract class Support {
	
	private String name;	// 解决问题的实例名称
	private Support next;	// 下一个解决实例
	
	public Support(String name) {
		this.name = name;
	}
	
	public Support setNext(Support next) {
		this.next = next;
		return next; 
	}
	
	@Override
	public String toString() {
		return "[ "+this.name+" ]";
	}
	
	public final void support(Trouble trouble) {		// 解决问题的步骤
		if(resolve(trouble)) {
			this.done(trouble);
		}else if(this.next!=null) {
			this.next.support(trouble);
		}else {
			this.fail(trouble);
		}
	}
	
	protected abstract boolean resolve(Trouble trouble); // 解决问题的方法
	
	protected void done(Trouble trouble) {				 // 解决
		System.out.println(trouble+"被"+this+"解决!");
	}
	
	protected void fail(Trouble trouble) {				 // 未解决
		System.out.println(trouble+"未被处理!");
	}

}
package com.wwq.ChainResponsibility.tj;

import com.wwq.ChainResponsibility.tj.bean.Trouble;

/**
 * 
 * @ClassName: NoSupport
 * @Description: 一个什么都处理不了的处理方案
 * @author: 王同学
 * @date: 2023年5月8日 下午4:12:04
 * @Copyright:
 */
public class NoSupport extends Support{

	public NoSupport(String name) {
		super(name);
	}

	@Override
	protected boolean resolve(Trouble trouble) {
		return false;
	}

}
package com.wwq.ChainResponsibility.tj;

import com.wwq.ChainResponsibility.tj.bean.Trouble;

/**
 * 
 * @ClassName: LimitSupport
 * @Description: 解决小于limit的错误
 * @author: 王同学
 * @date: 2023年5月8日 下午4:13:16
 * @Copyright:
 */
public class LimitSupport extends Support{

	private int limit;
	
	public LimitSupport(String name,int limit) {
		super(name);
		this.limit = limit;
	}

	@Override
	protected boolean resolve(Trouble trouble) {
		if(trouble.getNumber()<this.limit) {
			return true;
		}else {
			return false;
		}
	}

}
package com.wwq.ChainResponsibility.tj;

import com.wwq.ChainResponsibility.tj.bean.Trouble;

/**
 * 
 * @ClassName: OddSupport
 * @Description: 解决奇数编号的错误
 * @author: 王同学
 * @date: 2023年5月8日 下午4:16:27
 * @Copyright:
 */
public class OddSupport extends Support{

	public OddSupport(String name) {
		super(name);
	}

	@Override
	protected boolean resolve(Trouble trouble) {
		if(trouble.getNumber()%2==1) {
			return true;
		}else {
			return false;
		}
	}

}
package com.wwq.ChainResponsibility.tj;

import com.wwq.ChainResponsibility.tj.bean.Trouble;

/**
 * 
 * @ClassName: SpecialSupport
 * @Description: 解决指定编号的问题
 * @author: 王同学
 * @date: 2023年5月8日 下午4:17:58
 * @Copyright:
 */
public class SpecialSupport extends Support{

	private int number;
	
	public SpecialSupport(String name,int number) {
		super(name);
		this.number = number;
	}

	@Override
	protected boolean resolve(Trouble trouble) {
		if(trouble.getNumber()==this.number) {
			return true;
		}else {
			return false;
		}
	}

}
package com.wwq.ChainResponsibility.tj.bean;

/**
 * 
 * @ClassName: Trouble
 * @Description: 需要处理的问题
 * @author: 王同学
 * @date: 2023年5月8日 下午4:01:05
 * @Copyright:
 */
public class Trouble {

	private int number;	// 问题编号

	public Trouble(int number) {
		this.number = number;
	}
	
	public int getNumber() {
		return number;
	}

	public void setNumber(int number) {
		this.number = number;
	}
	
	@Override
	public String toString() {
		return "[ "+this.number+" ]";
	}
	
}
package com.wwq.ChainResponsibility.tj;

import com.wwq.ChainResponsibility.tj.bean.Trouble;

/**
 * 
 * @ClassName: Main
 * @Description: 测试
 * @author: 王同学
 * @date: 2023年5月8日 下午2:15:18
 * @Copyright:
 */
public class Main {

	public static void main(String[] args) {
		Support start = new NoSupport("start");
		Support bob = new LimitSupport("Bob", 100);
		Support charlie = new SpecialSupport("charlie", 429);
		Support diana = new LimitSupport("Diana", 200);
		Support elmo = new OddSupport("Elmo");
		Support fred = new LimitSupport("Fred", 300);
		
		// 形成责任链
		start.setNext(bob).setNext(charlie).setNext(diana).setNext(elmo).setNext(fred);
		
		for(int i=0;i<500;i++) { // 模拟解决问题
			start.support(new Trouble(i));
		}
	}
	
}

示例2-循环调用

将示例1中的示例代码,改为使用循环而不是递归。

public abstract class Support {
    private String name;                    // 解决问题的实例的名字
    private Support next;                   // 要推卸给的对象
    public Support(String name) {           // 生成解决问题的实例
        this.name = name;
    }
    public Support setNext(Support next) {  // 设置要推卸给的对象
        this.next = next;
        return next;
    }
    public void support(Trouble trouble) {
        for (Support obj = this; true; obj = obj.next) {
            if (obj.resolve(trouble)) {
                obj.done(trouble);
                break;
            } else if (obj.next == null) {
                obj.fail(trouble);
                break;
            }
        }
    }
    public String toString() {              // 显示字符串
        return "[" + name + "]";
    }
    protected abstract boolean resolve(Trouble trouble); // 解决问题的方法
    protected void done(Trouble trouble) {  // 解决
        System.out.println(trouble + " is resolved by " + this + ".");
    }
    protected void fail(Trouble trouble) {  // 未解决
        System.out.println(trouble + " cannot be resolved.");
    }
}
  • 注意:有些博客的示例中,将改为循环理解为使用List等容器来存储调用链。其实改为循环的核心目的是减少调用栈的资源占用(方法栈不递归深入)。

示例3-管道模式

将示例2中的示例代码,改为管道模式。

package com.wwq.ChainResponsibility.tj3;

import com.wwq.ChainResponsibility.tj.bean.Trouble;

/**
 * 
 * @ClassName: Support
 * @Description: 解决问题的抽象类
 * @author: 王同学
 * @date: 2023年5月8日 下午3:52:18
 * @Copyright:
 */
public abstract class Support {
	
	private String name;	// 解决问题的实例名称
	private Support next;	// 下一个解决实例
	
	public Support(String name) {
		this.name = name;
	}
	
	public Support setNext(Support next) {
		this.next = next;
		return next; 
	}
	
	@Override
	public String toString() {
		return "[ "+this.name+" ]";
	}
	
	public final void support(Trouble trouble) {		// 解决问题的步骤
		int count = 0;
		Support obj = this;
		do {
			if (obj.resolve(trouble)) {
				obj.done(trouble);
				count++;
            }
			obj=obj.next;
		}while(obj.next != null);
		
		if(count==0) {
			obj.fail(trouble);
		}
	}
	
	protected abstract boolean resolve(Trouble trouble); // 解决问题的方法
	
	protected void done(Trouble trouble) {				 // 解决
		System.out.println(trouble+"被"+this+"解决!");
	}
	
	protected void fail(Trouble trouble) {				 // 未解决
		System.out.println(trouble+"未被处理!");
	}

}
package com.wwq.ChainResponsibility.tj3;

import com.wwq.ChainResponsibility.tj.bean.Trouble;

/**
 * 
 * @ClassName: Main
 * @Description: 测试
 * @author: 王同学
 * @date: 2023年5月8日 下午2:15:18
 * @Copyright:
 */
public class Main {

	public static void main(String[] args) {
		Support start = new NoSupport("start");
		Support bob = new LimitSupport("Bob", 100);
		Support charlie = new SpecialSupport("charlie", 429);
		Support diana = new LimitSupport("Diana", 200);
		Support elmo = new OddSupport("Elmo");
		Support fred = new LimitSupport("Fred", 300);
		
		// 形成责任链
		start.setNext(bob).setNext(charlie).setNext(diana).setNext(elmo).setNext(fred);
		
		start.support(new Trouble(3));
	}
	
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值