为请求创建了一个接收者对象的链,对请求的发送者和接收者进行解耦
通常每个接收者都包含对另一个接收者的引用。如果一个对象不能处理该请求,那么它会把相同的请求传给下一个接收者,依此类推。
事例
需求:客户在支付订单时,可以享受多重优惠。
数据结构如图:
代码如下:
public interface Discount {
// 优惠后的实付金额。参数是优惠前的金额
float calculate(float payment);
}
public abstract class MultiDiscount implements Discount {
// 每个接收者都包含下一个接收者的引用
public MultiDiscount next;
}
实现类在完成自己工作后,要把请求交给下一个接收者处理
public class MultiDiscountA extends MultiDiscount {
@Override
public float calculate(float payment) {
// ...先按优惠策略A计算
float result = 95;
// 再传递给下一个接收者
if (next != null) {
result = next.calculate(result);
}
return result;
}
}
public class MultiDiscountB extends MultiDiscount {
@Override
public float calculate(float payment) {
// ...先按优惠策略B计算
float result = 90;
// 再传递给下一个接收者
if (next != null) {
result = next.calculate(result);
}
return result;
}
}
需要客户端来初始化整个责任链
测试:客户的订单100元,先享受优惠A再享受优惠B
public void test() {
MultiDiscount multiDiscountA = new MultiDiscountA();
MultiDiscount multiDiscountB = new MultiDiscountB();
// 优惠A的下一个是优惠B
multiDiscountA.next = multiDiscountB;
// 假设订单价格100元
multiDiscountA.calculate(100);
}
总结
适用场景
- 当多个对象要处理同一个请求时
- 需要动态为一个请求指定一组接收者时
- 一般用于拦截器、过滤器等,要实现统一的接口的请求
优点
- 降低耦合度
- 扩展性高。方便增删接收者
- 结构灵活。可动态增删、调整接收顺序
缺点
- 不保证责任链中的所有接收者都会处理请求,可能中途return
- 不易调试