设计模式10-策略模式与责任链模式详解
1.10.策略模式与责任链模式详解
1.10.1.策略模式详解
时长:1h15min
10.1.1.策略模式的定义
定义:
策略模式【Strategy Pattern】,又叫政策模式【Policy Pattern】,它是将定义的算法家族,分别封装起来,让它们之间可以相互替换,从而
让算法的变化不会影响到使用算法的用户。
可以避免多重分支的if...else...和switch语句。
属于行为型模式。
10.1.1.1.策略模式在生活中应用场景
阶梯个税【工资收入不同,个税算法不同】
移动支付方式选择【微信,支付宝,银联】
出行交通方式选择【火车,飞机,汽车,轮船】
10.1.1.1、2.策略模式的应用场景
1.假如系统中有很多类,而他们的区别仅仅在于他们的行为 不同。
2.一个系统需要动态地在几种算法中选择一种。
3.需要屏蔽算法规则。
10.1.2.策略模式的通用实现
10.1.2.1.类图设计
10.1.2.2.代码实现
1.顶层策略接口
package com.wf.strategy.general; /** * @ClassName IStrategy * @Description 顶层策略接口 * @Author wf * @Date 2020/6/18 10:11 * @Version 1.0 */ public interface IStrategy { /** * 算法接口 */ void algorithm(); }
2.策略子类实现
package com.wf.strategy.general; /** * @ClassName ConcreteStrategyA * @Description 具体策略子类A * @Author wf * @Date 2020/6/18 10:13 * @Version 1.0 */ public class ConcreteStrategyA implements IStrategy { @Override public void algorithm() { System.out.println("这是算法A"); } } package com.wf.strategy.general; /** * @ClassName ConcreteStrategyB * @Description 具体策略子类B * @Author wf * @Date 2020/6/18 10:13 * @Version 1.0 */ public class ConcreteStrategyB implements IStrategy { @Override public void algorithm() { System.out.println("这是算法B"); } }
3.上下文对象
package com.wf.strategy.general; /** * @ClassName Context * @Description 上下文对象 * @Author wf * @Date 2020/6/18 10:14 * @Version 1.0 */ public class Context { private IStrategy strategy; public Context(IStrategy strategy) { this.strategy = strategy; } //由构造器中传参实现子类类型,来决定选择哪一种算法 public void algorithm(){ this.strategy.algorithm(); } }
4.测试类
package com.wf.strategy.general; /** * @ClassName Test * @Description 测试类 * @Author wf * @Date 2020/6/18 10:15 * @Version 1.0 */ public class Test { public static void main(String[] args) { //使用时,客户选择一种策略 IStrategy strategy = new ConcreteStrategyA(); //封装到上下文中 Context context = new Context(strategy); //调用策略方法 context.algorithm(); } }
测试结果如下:
10.1.3.策略模式的实现示例之促销案例
10.1.3.1.代码实现
1.顶层接口
package com.wf.strategy.demo.promotion; /** * @ClassName IPromotionStrategy * @Description 促销策略接口 * @Author wf * @Date 2020/6/18 10:31 * @Version 1.0 */ public interface IPromotionStrategy { /** * 促销方法 */ void doPromotion(); }
2.实现子类
package com.wf.strategy.demo.promotion; /** * @ClassName GroupPurchaseStrategy * @Description 团购促销 * @Author wf * @Date 2020/6/18 10:36 * @Version 1.0 */ public class GroupPurchaseStrategy implements IPromotionStrategy{ @Override public void doPromotion() { System.out.println("5人成团,可以优惠"); } } package com.wf.strategy.demo.promotion; /** * @ClassName CashRollbackStrategy * @Description 返现促销 * @Author wf * @Date 2020/6/18 10:34 * @Version 1.0 */ public class CashRollbackStrategy implements IPromotionStrategy { @Override public void doPromotion() { System.out.println("返现,直接打款到支付宝帐号"); } } package com.wf.strategy.demo.promotion; /** * @ClassName CouponStrategy * @Description 优惠券促销方式 * @Author wf * @Date 2020/6/18 10:33 * @Version 1.0 */ public class CouponStrategy implements IPromotionStrategy { @Override public void doPromotion() { System.out.println("使用优惠券抵扣"); } } package com.wf.strategy.demo.promotion; /** * @ClassName EmptyStrategy * @Description 无优惠购买 * @Author wf * @Date 2020/6/18 10:37 * @Version 1.0 */ public class EmptyStrategy implements IPromotionStrategy { @Override public void doPromotion() { System.out.println("原价购买,无优惠"); } }
3.测试类
public static void main(String[] args) { String promotion = ""; IPromotionStrategy strategy = null; if("团购".equals(promotion)){ strategy = new GroupPurchaseStrategy(); }else if("".equals(promotion)){ //... strategy = new EmptyStrategy(); } strategy.doPromotion(); }
测试结果:
说明:
这里并没有使用策略模式,而是通过分支判断,多态的方式来实现。
4.策略模式运用---增加上下文对象
package com.wf.strategy.demo.promotion; /** * @ClassName PromotionActivity * @Description 上下文对象,促销活动 * @Author wf * @Date 2020/6/18 10:45 * @Version 1.0 */ public class PromotionActivity { private IPromotionStrategy strategy; public PromotionActivity(IPromotionStrategy strategy) { this.strategy = strategy; } public void execute(){ strategy.doPromotion(); } }
修改测试代码如下:
public static void main(String[] args) { String promotion = ""; PromotionActivity activity = null; if("团购".equals(promotion)){ activity = new PromotionActivity(new GroupPurchaseStrategy()); }else if("".equals(promotion)){ //... activity = new PromotionActivity(new EmptyStrategy()); } activity.execute(); //说明: //这里仍然需要进行if...else分支判断,代码仍然不够优雅 //解决这个问题,通常使用策略模式 + 简单工厂模式 }
说明:
//这里仍然需要进行if...else分支判断,代码仍然不够优雅 //解决这个问题,通常使用策略模式 + 简单工厂模式
5.引入简单工厂优化
package com.wf.strategy.demo.promotion; import java.util.HashMap; import java.util.Map; import java.util.Set; /** * @ClassName PromotionStrategyFactory * @Description 上下文对象创建工厂 * @Author wf * @Date 2020/6/18 10:52 * @Version 1.0 */ public class PromotionStrategyFactory { private static Map<String,IPromotionStrategy> promotionStrategyMap = new HashMap<String,IPromotionStrategy>(); private static final IPromotionStrategy EMPTY = new EmptyStrategy(); static{ promotionStrategyMap.put(PromotionKey.COUPON,new CouponStrategy()); promotionStrategyMap.put(PromotionKey.CASH_ROLLBACK,new CashRollbackStrategy()); promotionStrategyMap.put(PromotionKey.GROUP_PURCHASE,new GroupPurchaseStrategy()); } private PromotionStrategyFactory(){} public static IPromotionStrategy getPromotionStrategy(String promotionKey){ IPromotionStrategy strategy = promotionStrategyMap.get(promotionKey); return strategy == null ? EMPTY : strategy; } //定义内部接口,定义key private interface PromotionKey{ String COUPON = "COUPON"; String CASH_ROLLBACK = "CASH_ROLLBACK"; String GROUP_PURCHASE = "GROUP_PURCHASE"; } public Set<String> getPromotionKeys(){ return promotionStrategyMap.keySet(); } }
修改测试类:
public static void main(String[] args) { String promotionKey = "COUPON"; IPromotionStrategy strategy = PromotionStrategyFactory.getPromotionStrategy(promotionKey); strategy.doPromotion(); }
测试结果如下:
说明:
分支判断,移到工厂类中去处理。
10.1.3.2.系统类图
10.1.4.策略模式的实现示例之支付方式选择案例
10.1.4.1.代码实现
1.顶层接口
package com.wf.strategy.demo.pay.payport; import com.wf.strategy.demo.pay.MsgResult; /** * @ClassName Payment * @Description 支付抽象接口 * @Author wf * @Date 2020/6/18 11:31 * @Version 1.0 */ public abstract class Payment { public abstract String getName(); public MsgResult pay(String uid, double amount){ //查询余额是否足够 if(queryBalance(uid) < amount){ return new MsgResult(500,"支付失败","余额不足"); } return new MsgResult(200,"支付成功","支付金额:"+amount); } protected abstract double queryBalance(String uid); }
2.子类实现
package com.wf.strategy.demo.pay.payport; /** * @ClassName WechatPay * @Description 微信支付 * @Author wf * @Date 2020/6/18 14:27 * @Version 1.0 */ public class WechatPay extends Payment { @Override public String getName() { return "微信支付"; } @Override protected double queryBalance(String uid) { return 500; } } package com.wf.strategy.demo.pay.payport; /** * @ClassName JDPay * @Description 京东白条支付 * @Author wf * @Date 2020/6/18 14:25 * @Version 1.0 */ public class JDPay extends Payment { @Override public String getName() { return "京东白条"; } @Override protected double queryBalance(String uid) { return 500; } } package com.wf.strategy.demo.pay.payport; /** * @ClassName BankUnionPay * @Description 银联支付 * @Author wf * @Date 2020/6/18 14:28 * @Version 1.0 */ public class BankUnionPay extends Payment { @Override public String getName() { return "银联支付"; } @Override protected double queryBalance(String uid) { return 120; } } package com.wf.strategy.demo.pay.payport; /** * @ClassName AliPay * @Description 支付宝支付 * @Author wf * @Date 2020/6/18 14:23 * @Version 1.0 */ public class AliPay extends Payment { @Override public String getName() { return "支付宝"; } @Override protected double queryBalance(String uid) { return 900; } }
3.订单类
package com.wf.strategy.demo.pay; import com.wf.strategy.demo.pay.payport.PayStrategy; import com.wf.strategy.demo.pay.payport.Payment; /** * @ClassName Order * @Description 订单类 * @Author wf * @Date 2020/6/18 14:29 * @Version 1.0 */ public class Order { private String uid; private String orderId; private double amount; public Order(String uid, String orderId, double amount) { this.uid = uid; this.orderId = orderId; this.amount = amount; } public MsgResult pay(){ return pay(PayStrategy.DEFAULT_PAY); } public MsgResult pay(String payKey){ Payment payment = PayStrategy.get(payKey); System.out.println("欢迎使用:"+payment.getName()); System.out.println("本次交易金额为:"+amount+",开始扣款"); return payment.pay(uid,amount); } }
4.上下文对象
package com.wf.strategy.demo.pay.payport; import java.util.HashMap; import java.util.Map; /** * @ClassName PayStrategy * @Description 支付策略,上下文对象 * @Author wf * @Date 2020/6/18 14:32 * @Version 1.0 */ public class PayStrategy { public static final String ALI_PAY = "AliPay"; public static final String JD_PAY = "JdPay"; public static final String WECHAT_PAY = "WechatPay"; public static final String BANKUINION_PAY = "BankUnionPay"; public static final String DEFAULT_PAY = "AliPay"; private static Map<String,Payment> strategyMap = new HashMap<String, Payment>(); static { strategyMap.put(ALI_PAY,new AliPay()); strategyMap.put(JD_PAY,new JDPay()); strategyMap.put(WECHAT_PAY,new WechatPay()); strategyMap.put(BANKUINION_PAY,new BankUnionPay()); } public static Payment get(String payKey){ if(!strategyMap.containsKey(payKey)){ return strategyMap.get(DEFAULT_PAY); } return strategyMap.get(payKey); } }
5.结果集po
package com.wf.strategy.demo.pay; /** * @ClassName MsgResult * @Description 结果集 * @Author wf * @Date 2020/6/18 11:36 * @Version 1.0 */ public class MsgResult { private int code; private Object data; private String msg; public MsgResult(int code, String msg, Object data) { this.code = code; this.data = data; this.msg = msg; } @Override public String toString() { return "MsgResult{" + "code='" + code + '\'' + ", data=" + data + ", msg='" + msg + '\'' + '}'; } }
6.测试类
package com.wf.strategy.demo.pay; import com.sun.org.apache.xpath.internal.operations.Or; import com.wf.strategy.demo.pay.payport.PayStrategy; /** * @ClassName Test * @Description 测试类 * @Author wf * @Date 2020/6/18 14:43 * @Version 1.0 */ public class Test { public static void main(String[] args) { Order order = new Order("1","20200618012222",324.5); System.out.println(order.pay(PayStrategy.BANKUINION_PAY)); } }
测试结果如下:
10.1.4.2.类图设计
10.1.5.策略模式在源码中应用
10.1.5.1.jdk中Comparator接口
int compare(T o1, T o2);
表示列表中前后两个元素进行比较,如果返回值大于0,表示升序。
它的实现类,在Arrays中parallelSort方法有定义:
public static <T> void parallelSort(T[] a, Comparator<? super T> cmp) { if (cmp == null) cmp = NaturalOrder.INSTANCE; //默认策略 int n = a.length, p, g; if (n <= MIN_ARRAY_SORT_GRAN || (p = ForkJoinPool.getCommonPoolParallelism()) == 1) TimSort.sort(a, 0, n, cmp, null, 0, 0); else new ArraysParallelSortHelpers.FJObject.Sorter<T> (null, a, (T[])Array.newInstance(a.getClass().getComponentType(), n), 0, n, 0, ((g = n / (p << 2)) <= MIN_ARRAY_SORT_GRAN) ? MIN_ARRAY_SORT_GRAN : g, cmp).invoke(); }
默认策略中调用:
static final class NaturalOrder implements Comparator<Object> { @SuppressWarnings("unchecked") public int compare(Object first, Object second) { return ((Comparable<Object>)first).compareTo(second); } static final NaturalOrder INSTANCE = new NaturalOrder(); }
10.1.5.2.spring中Resource接口
10.1.5.3.spring中InstantiationStrategy接口
10.1.6.策略模式使用总结
10.1.6.1.优缺点总结
优点:
符合开闭原则
避免使用多重条件判断,如:if...else if...,switch
使用策略模式可以提高算法的保密性和安全性。
缺点:
客户端必须要知道所有的策略,并且自行选择使用哪一个策略。
可以通过字典表配置成枚举参数,当用户点击时,弹出所有策略。任选一个。
代码中会增加非常多的策略类,增加维护难度 。
1.10.2.责任链模式详解
时长:46min
10.2.1.责任链模式定义
定义:
Chain of Responsibility Pattern,是将链中每一个节点看作是一个对象,每个节点处理的请求均不同,且内部自动维护一个
下一节点的对象。当一个请求从链式的首端发现时,会沿着链的路径依次传递给每一个节点对象,直至对象处理完这个请求为止。
属于行为型模式。
10.2.1.1.在生活中应用
工作流中审批流程
过五关,斩六将
10.2.1.2.责任链模式的适用场景
1.多个对象处理同一个请求,但具体哪个对象处理则在运行时动态决定
2.在不明确指定接收者的前提下,向多个对象中的一个提交一个请求
3.可动态地指定一组对象处理请求
10.2.2.责任链模式通用设计
10.2.2.1.类图设计
10.2.2.2.代码实现
1.顶层抽象处理器
package com.wf.chain.general; /** * @ClassName Handler * @Description 处理器 * @Author wf * @Date 2020/6/18 15:52 * @Version 1.0 */ public abstract class Handler { protected Handler nextHandle; public void setNextHandle(Handler nextHandle) { this.nextHandle = nextHandle; } public abstract void handleRequest(String request); }
2.处理器子类
package com.wf.chain.general; /** * @ClassName ConcreteHandlerA * @Description 实现子类A * @Author wf * @Date 2020/6/18 15:54 * @Version 1.0 */ public class ConcreteHandlerA extends Handler { @Override public void handleRequest(String request) { if("requestA".equals(request)){ System.out.println(this.getClass().getSimpleName() + " deal with request:" + request); return; } if(this.nextHandle != null){ this.nextHandle.handleRequest(request); } } } package com.wf.chain.general; /** * @ClassName ConcreteHandlerB * @Description 实现子类B * @Author wf * @Date 2020/6/18 15:54 * @Version 1.0 */ public class ConcreteHandlerB extends Handler { @Override public void handleRequest(String request) { if("requestB".equals(request)){ System.out.println(this.getClass().getSimpleName() + " deal with request:" + request); return; } if(this.nextHandle != null){ this.nextHandle.handleRequest(request); } } }
3.测试类
package com.wf.chain.general; /** * @ClassName Test * @Description 测试类 * @Author wf * @Date 2020/6/18 15:55 * @Version 1.0 */ public class Test { public static void main(String[] args) { Handler handlerA = new ConcreteHandlerA(); Handler handlerB = new ConcreteHandlerB(); //设置链关系,先A后B handlerA.setNextHandle(handlerB); handlerA.handleRequest("requestB"); } }
测试结果:
10.2.3.责任链模式应用之用户登录校验
10.2.3.1.代码实现
1.员工bean定义
package com.wf.chain.demo.auth; /** * @ClassName Member * @Description 员工类,业务bean * @Author wf * @Date 2020/6/18 16:07 * @Version 1.0 */ public class Member { //登录名 private String loginName; //登录密码 private String loginPass; //员工权限 private String roleName; public Member(String loginName, String loginPass) { this.loginName = loginName; this.loginPass = loginPass; } public String getLoginName() { return loginName; } public void setLoginName(String loginName) { this.loginName = loginName; } public String getLoginPass() { return loginPass; } public void setLoginPass(String loginPass) { this.loginPass = loginPass; } public String getRoleName() { return roleName; } public void setRoleName(String roleName) { this.roleName = roleName; } }
2.登录服务
package com.wf.chain.demo.auth.old; import org.springframework.util.StringUtils; /** * @ClassName MemberService * @Description 员工类服务接口 * @Author wf * @Date 2020/6/18 16:07 * @Version 1.0 */ public class MemberService { public void login(String loginName, String loginPass){ //入参判空 if(StringUtils.isEmpty(loginName) || StringUtils.isEmpty(loginPass)){ System.out.println("用户名和密码为空"); return; } System.out.println("用户名和密码不为空,可以往下执行了"); Member member = checkExist(loginName,loginPass); if(null == member){ System.out.println("用户不存在"); return; } //用户名存在,表示可登录 System.out.println("登录成功"); if(!"管理员".equals(member.getRoleName())){ System.out.println("您不是管理员,没有操作权限"); } System.out.println("允许操作"); } private Member checkExist(String loginName, String loginPass) { Member member = new Member(loginName,loginPass); member.setRoleName("管理员"); return member; } }
说明:
login方法中,需要进行一系列的校验。入参判空校验,用户名存在性校验,用户权限校验。。。
这些校验可能会非常复杂,写在一个方法中,方法的职责过重,需要进行拆分。
因此,考虑将几部分校验逻辑进行拆分。就将3个处理,分别拆分,串联成一个责任链。
3.使用责任链模式优化代码
【1】定义顶层抽象handler
package com.wf.chain.demo.auth.optimize; import com.wf.chain.demo.auth.Member; /** * @ClassName Handler * @Description 定义抽象处理器 * @Author wf * @Date 2020/6/18 16:28 * @Version 1.0 */ public abstract class Handler { protected Handler next; public void next(Handler next) { this.next = next; } public abstract void doHandle(Member member); }
【2】定义处理实现子类
package com.wf.chain.demo.auth.optimize; import com.wf.chain.demo.auth.Member; import org.springframework.util.StringUtils; /** * @ClassName ValidateHandler * @Description 入参判空处理 * @Author wf * @Date 2020/6/18 16:30 * @Version 1.0 */ public class ValidateHandler extends Handler { @Override public void doHandle(Member member) { //入参判空 if(StringUtils.isEmpty(member.getLoginName()) || StringUtils.isEmpty(member.getLoginPass())){ System.out.println("用户名和密码为空"); return; } System.out.println("用户名和密码不为空,可以往下执行了"); //向下传递 next.doHandle(member); } } package com.wf.chain.demo.auth.optimize; import com.wf.chain.demo.auth.Member; /** * @ClassName LoginHandler * @Description 登录校验,判断用户存在性 * @Author wf * @Date 2020/6/18 16:35 * @Version 1.0 */ public class LoginHandler extends Handler { @Override public void doHandle(Member member) { Member existMember = checkExist(member.getLoginName(),member.getLoginPass()); if(null == existMember){ System.out.println("用户不存在"); return; } //用户名存在,表示可登录 System.out.println("登录成功"); next.doHandle(existMember); } private Member checkExist(String loginName, String loginPass) { Member member = new Member(loginName,loginPass); member.setRoleName("管理员"); return member; } } package com.wf.chain.demo.auth.optimize; import com.wf.chain.demo.auth.Member; /** * @ClassName AuthHandler * @Description 权限校验处理器 * @Author wf * @Date 2020/6/18 16:38 * @Version 1.0 */ public class AuthHandler extends Handler { @Override public void doHandle(Member member) { if(!"管理员".equals(member.getRoleName())){ System.out.println("您不是管理员,没有操作权限");
return; } System.out.println("允许操作"); } }
【3】优化Service服务逻辑
package com.wf.chain.demo.auth.optimize; import com.wf.chain.demo.auth.Member; import org.springframework.util.StringUtils; /** * @ClassName MemberService * @Description 员工类服务接口 * @Author wf * @Date 2020/6/18 16:07 * @Version 1.0 */ public class MemberService { public void login(String loginName, String loginPass){ //通过责任链来处理 Handler validateHandler = new ValidateHandler(); Handler loginHandler = new LoginHandler(); Handler authHandler = new AuthHandler(); loginHandler.next(authHandler); validateHandler.next(loginHandler); validateHandler.doHandle(new Member(loginName,loginPass)); } }
【4】.测试类
package com.wf.chain.demo.auth; import com.wf.chain.demo.auth.optimize.MemberService; /** * @ClassName Test * @Description 测试类 * @Author wf * @Date 2020/6/18 16:43 * @Version 1.0 */ public class Test { public static void main(String[] args) { MemberService service = new MemberService(); service.login("wf","@g;aj;132"); } }
测试结果如下:
说明:
这里引入优化后的service服务,达到一样的效果,代码优雅度提升太多。
但是,service中使用next方法来,建立责任链关系。让人很头昏,难以理解。
希望可以进一步优化。
在建造者模式中,我们去体会到了链式编程的好处,可以用来做优化。使用add来建立关系,就很容易理解了。
4.责任链模式结合建造者模式优化代码
【1】顶层Hanlder修改
package com.wf.chain.demo.auth.builderchain; import com.wf.chain.demo.auth.Member; /** * @ClassName Handler * @Description 定义抽象处理器 * @Author wf * @Date 2020/6/18 16:28 * @Version 1.0 */ public abstract class Handler<T> { protected Handler next; public void next(Handler next) { this.next = next; } public abstract void doHandle(Member member); public static class Builder<T> { private Handler<T> head; private Handler<T> tail; public Builder<T> addHandler(Handler handler){ if(this.head == null){ this.head = this.tail = handler; return this; } //头部已有元素,从尾部开始追加 this.tail.next(handler);//添加下一个元素 this.tail = handler; //指针位置移动一位,同时head也指向下一个 return this; } public Handler<T> build(){ return this.head; } } }
【2】处理器子类实现不变
【3】service服务修改
package com.wf.chain.demo.auth.builderchain; import com.wf.chain.demo.auth.Member; /** * @ClassName MemberService * @Description 员工类服务接口 * @Author wf * @Date 2020/6/18 16:07 * @Version 1.0 */ public class MemberService { public void login(String loginName, String loginPass){ //通过责任链来处理 Handler.Builder builder = new Handler.Builder(); builder.addHandler(new ValidateHandler()) .addHandler(new LoginHandler()) .addHandler(new AuthHandler()); builder.build().doHandle(new Member(loginName,loginPass)); } }
说明:
可以看到,login中的处理逻辑,显得很清楚,易于理解。
【4】测试类修改
package com.wf.chain.demo.auth.builderchain; /** * @ClassName Test * @Description 测试类 * @Author wf * @Date 2020/6/18 16:43 * @Version 1.0 */ public class Test { public static void main(String[] args) { MemberService service = new MemberService(); service.login("wf","@g;aj;132"); // service.login("wf",null); // service.login("wf",""); } }
说明:
这个优化过程,重点在于Handler的处理。
对于链表的处理,在框架中多处理为双向链表,如下所示代码:
public abstract class Handler<T> { protected Handler next; public void next(Handler next) { this.next = next; } public abstract void doHandle(Member member); public static class Builder<T> { private Handler<T> head; private Handler<T> tail; public Builder<T> addHandler(Handler handler){ do { if (this.head == null) { this.head = this.tail = handler; //return this; break; } //头部已有元素,从尾部开始追加 this.tail.next(handler);//添加下一个元素 this.tail = handler; //指针位置移动一位,同时head也指向下一个 }while (false); //真正在框架中,如果是双向链表,会判断是否已经到达尾部 return this; } public Handler<T> build(){ return this.head; } } }
10.2.4.责任链模式在源码中的应用
10.2.4.1.servlet中Filter
需要引入mvn依赖:
<dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> <version>2.5</version> <scope>provided</scope> </dependency>
搜索:Filter,如下所示:
package javax.servlet; import java.io.IOException; public interface Filter { void init(FilterConfig var1) throws ServletException; void doFilter(ServletRequest var1, ServletResponse var2, FilterChain var3) throws IOException, ServletException; void destroy(); }
doFilter中传参FilterChain,源码如下:
package javax.servlet; import java.io.IOException; public interface FilterChain { void doFilter(ServletRequest var1, ServletResponse var2) throws IOException, ServletException; }
10.2.4.2.netty中ChannelPipeline
需要引入mvn依赖包:
<dependency> <groupId>io.netty</groupId> <artifactId>netty-all</artifactId> <version>4.1.42.Final</version> </dependency>
找到默认实现DefaultChannelPipeline,如下所示:
final AbstractChannelHandlerContext head; final AbstractChannelHandlerContext tail;
ChannelHandler
在权限安全校验框架中,大量使用责任链模式。如:
spring security/apache shiro
10.2.4.责任链模式使用总结
10.2.4.1.优缺点总结
优点:
1.将请求与处理解耦
2.请求处理者【节点对象】只需要关注自己感兴趣的请求进行处理即可。对于不感兴趣的请求,
直接转发给下一节点对象。
3.具备链式传递处理请求功能,请求发送者无需知晓链路结构,只需等待请求处理结果。
4.链路结构灵活,可以通过改变链路结构动态地新增或删减责任。
5.易于扩展新的请求处理类(节点),符合开闭原则。
缺点:
1.责任链太长或者处理时间过长,会影响整体性能。
2.如果节点对象存在循环引用,会造成死循环,导致系统崩溃。