设计模式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.如果节点对象存在循环引用,会造成死循环,导致系统崩溃。

 

posted @ 2020-06-18 15:28  我爱钻研  阅读(6313)  评论(0编辑  收藏  举报