编程是一门艺术,大批量的改动显然是非常丑陋的做法,用心的琢磨写的代码让它变的更美观。
在现实生活中,一个事件需要经过多个对象处理是很常见的场景。例如,采购审批流程、请假流程等。公司员工请假,可批假的领导有部门负责人、副总经理、总经理等,但每个领导能批准的天数不同,员工必须根据需要请假的天数去找不同的领导签名,也就是说员工必须记住每个领导的姓名、电话和地址等信息,这无疑增加了难度。
在计算机软硬件中也有相关例子,如异常处理中,处理程序根据异常的类型决定自己是否处理该异常;还有 OkHttp的拦截器,这些都可以考虑使用责任链模式来实现。
责任链(Chain of Responsibility)模式:为了避免请求发送者与多个请求处理者耦合在一起,于是将所有请求的处理者通过前一对象记住其下一个对象的引用而连成一条链;当有请求发生时,可将请求沿着这条链传递,直到有对象处理它为止。
责任链模式是一种对象行为型模式其主要优点:
其主要不足:
通常情况下,可以通过数据链表来实现职责链模式的数据结构
职责链模式主要包含以下角色:
责任链模式的本质是解耦请求与处理,让请求在处理链中能进行传递与被处理;理解责任链模式应当理解其模式,而不是其具体实现。责任链模式的独到之处是将其节点处理者组合成了链式结构,并允许节点自身决定是否进行请求处理或转发,相当于让请求流动起来。
场景描述:购买商品打折:假如打折可以叠加,只要符合要求,各种折扣都可以叠加使用。
/** * 责任链实现的关键是 定义一个next节点 然后构建一个链式结构 */ public abstract class MultyDiscount implements Discount { /** * 链的下一个节点 */ protected MultyDiscount nextMultyDiscount; /** * 通过构造函数 将下一个节点链接起来 * @param nextMultyDiscount */ public MultyDiscount(MultyDiscount nextMultyDiscount){ this.nextMultyDiscount = nextMultyDiscount; } @Override public int calculate(int money) { if (nextMultyDiscount!=null){ this.nextMultyDiscount.calculate(money); } return money; } } public class FullMultyDiscount extends MultyDiscount{ /** * 通过构造函数 将下一个节点链接起来 * * @param nextMultyDiscount */ public FullMultyDiscount(MultyDiscount nextMultyDiscount) { super(nextMultyDiscount); } @Override public int calculate(int money) { /*先执行满减操作*/ if (money > 200){ System.out.println("优惠满减20元"); money = money - 20; } /*父类的方法执行的是成员变量的优惠方案,也就是节点的优惠方案*/ return super.calculate(money); } } /** * 假日一律减5元 */ public class HolidayMultyDiscount extends MultyDiscount { /** * 公共的下一个节点 存放在父类节点上 * @param nextMultyDiscount */ public HolidayMultyDiscount(MultyDiscount nextMultyDiscount) { super(nextMultyDiscount); } @Override public int calculate(int money) { if (money > 20){ System.out.println("假日一律减5元"); money = money - 5; } return super.calculate(money); } } /** * 首次购 花费多100元 减免30 */ public class NewerMultyDiscount extends MultyDiscount { public NewerMultyDiscount(MultyDiscount nextMultyDiscount) { super(nextMultyDiscount); } @Override public int calculate(int money) { if (money > 100){ System.out.println("首次购买减30元"); money = money - 30; } return super.calculate(money); } } /** * 第二单8折优惠 */ public class SecondMultyDiscount extends MultyDiscount { public SecondMultyDiscount(MultyDiscount nextMultyDiscount) { super(nextMultyDiscount); } @Override public int calculate(int money) { System.out.println("第二单打8折"); Double balance = money * 0.8; return super.calculate(balance.intValue()); } } public class ChainCartClient { /*初始化满减优惠券 满减没有下一个节点 是最后一个节点*/ private static MultyDiscount multyDiscount = new FullMultyDiscount(null); static { /*新用户减免优惠是 满减优惠*/ multyDiscount = new NewerMultyDiscount(multyDiscount); /*第二单打折扣的下一个节点是新用户减免*/ multyDiscount = new SecondMultyDiscount(multyDiscount); /*假日的下一个节点是 第二单打折扣*/ multyDiscount = new HolidayMultyDiscount(multyDiscount); } public static void main(String[] args) { List<Fruit> products = new ArrayList(); products.add(StaticFactory.getFruitApple()); products.add(StaticFactory.getFruitBanana()); products.add(StaticFactory.getFruitOrange()); ShoppingCart cart = new OtherPayShopping(products); /*注入优惠方案*/ cart.setDiscount(multyDiscount); cart.submitOrder(); } }
责任链设计模式这个实例中,两个关键点:一个是需要一个成员变量存储下一个节点,第二个就是建立一个链式结构的数据。
责任链模式通常在以下几种情况使用:
多个对象可以处理一个请求,但具体由哪个对象处理该请求在运行时自动确定。可动态指定一组对象处理请求,或添加新的处理者。需要在不明确指定请求处理者的情况下,向多个处理者中的一个提交请求。