定义:
策略模式【Strategy Pattern】,又叫政策模式【Policy Pattern】,它是将定义的算法家族,分别封装起来,让它们之间可以相互替换,从而
让算法的变化不会影响到使用算法的用户。
可以避免多重分支的if…else…和switch语句。
属于行为型模式。
阶梯个税【工资收入不同,个税算法不同】
移动支付方式选择【微信,支付宝,银联】
出行交通方式选择【火车,飞机,汽车,轮船】
1.假如系统中有很多类,而他们的区别仅仅在于他们的行为 不同。
2.一个系统需要动态地在几种算法中选择一种。
3.需要屏蔽算法规则。
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();
}
}
测试结果如下:
.策略模式的实现示例之促销案例
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();
}
说明:
分支判断,移到工厂类中去处理。
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));
}
}
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();
}
复制代码
优点:
符合开闭原则
避免使用多重条件判断,如:if…else if…,switch
使用策略模式可以提高算法的保密性和安全性。
缺点:
客户端必须要知道所有的策略,并且自行选择使用哪一个策略。
可以通过字典表配置成枚举参数,当用户点击时,弹出所有策略。任选一个。
代码中会增加非常多的策略类,增加维护难度 。
定义:
Chain of Responsibility Pattern,是将链中每一个节点看作是一个对象,每个节点处理的请求均不同,且内部自动维护一个
下一节点的对象。当一个请求从链式的首端发现时,会沿着链的路径依次传递给每一个节点对象,直至对象处理完这个请求为止。
属于行为型模式。
工作流中审批流程
过五关,斩六将
1.多个对象处理同一个请求,但具体哪个对象处理则在运行时动态决定
2.在不明确指定接收者的前提下,向多个对象中的一个提交一个请求
3.可动态地指定一组对象处理请求
10.2.2.责任链模式通用设计
10.2.2.1.类图设计
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");
}
}
复制代码
测试结果:
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;
}
}
}
需要引入mvn依赖:
<dependency>
<groupId>javax.servletgroupId>
<artifactId>servlet-apiartifactId>
<version>2.5version>
<scope>providedscope>
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
优点:
1.将请求与处理解耦
2.请求处理者【节点对象】只需要关注自己感兴趣的请求进行处理即可。对于不感兴趣的请求,
直接转发给下一节点对象。
3.具备链式传递处理请求功能,请求发送者无需知晓链路结构,只需等待请求处理结果。
4.链路结构灵活,可以通过改变链路结构动态地新增或删减责任。
5.易于扩展新的请求处理类(节点),符合开闭原则。
缺点:
1.责任链太长或者处理时间过长,会影响整体性能。
2.如果节点对象存在循环引用,会造成死循环,导致系统崩溃。