首页 > 其他 > 详细

11. 策略模式与责任连模式

时间:2021-03-30 20:47:51      阅读:17      评论:0      收藏:0      [点我收藏+]

一、策略模式

1、策略模式 [ Strategy Pattern ] 又叫政策模式 [ Policy Pattern ],它是将定义得算法家族、分别封装起来,让他们之间可以互相替换,从而让算法得变化不会影响到使用算法的用户

2、可以避免多重分支的 if...else...和 switch 语句

3、属于《行为型模式》

【适用场景】

1、假如系统种有很多类,而他们的区别仅仅在于他们的行为不同

2、一个系统需要动态的再几种算法种选择一种

3、需要屏蔽算法规则

1. 优惠策略

//优惠策略
public interface IPromotionStrategy {
    void doPromotion();
}
//优惠券
public class CouponStrategy implements IPromotionStrategy {
    public void doPromotion() {
        System.out.println("使用优惠券抵扣");
    }
}
//返现
public class CashbackStrategy implements IPromotionStrategy {
    public void doPromotion() {
        System.out.println("返现,直接打款到支付宝账号");
    }
}
//拼团
public class GroupbuyStrategy implements IPromotionStrategy {
    public void doPromotion() {
        System.out.println("5人成团,可以优惠");
    }
}
//无优惠
public class EmptyStrategy implements IPromotionStrategy {
    public void doPromotion() {
        System.out.println("无优惠");
    }
}
//调用
public static void main(String[] args) {
    String promotion = "";
    IPromotionStrategy strategy = null;
	if("团购".equals(promotion)){
        new PromotionActivity(new GroupbuyStrategy());
    }else if("".equals(promotion)){
        //很不优雅,怎么办呢?
    }else if("".equals(promotion)){
        
    }
    strategy.doPromotion();
}
/*
优化
	1、加入上下文
	2、加入策略工厂
*/
//上下文
public class PromotionActivity {
    private IPromotionStrategy strategy;
    public PromotionActivity(IPromotionStrategy strategy) {
        this.strategy = strategy;
    }
    public void execute(){
        strategy.doPromotion();
    }
}
//策略工厂
public class PromotionStrategyFacory {
    private static Map<String,IPromotionStrategy> PROMOTIONS = new HashMap<String,IPromotionStrategy>();
    static {
        PROMOTIONS.put(PromotionKey.COUPON,new CouponStrategy());
        PROMOTIONS.put(PromotionKey.CASHBACK,new CashbackStrategy());
        PROMOTIONS.put(PromotionKey.GROUPBUY,new GroupbuyStrategy());
    }
    private static final IPromotionStrategy EMPTY = new EmptyStrategy();
    private PromotionStrategyFacory(){}
    public static IPromotionStrategy getPromotionStrategy(String promotionKey){
        IPromotionStrategy strategy = PROMOTIONS.get(promotionKey);
        return strategy == null ? EMPTY : strategy;
    }
    private interface PromotionKey{
        String COUPON = "COUPON";
        String CASHBACK = "CASHBACK";
        String GROUPBUY = "GROUPBUY";
    }
    public static  Set<String> getPromotionKeys(){
        return PROMOTIONS.keySet();
    }
}
//调用
public static void main(String[] args) {
    //PromotionStrategyFacory.getPromotionKeys();
    String promotionKey = "COUPON";
    IPromotionStrategy promotionStrategy = PromotionStrategyFacory.getPromotionStrategy(promotionKey);
    promotionStrategy.doPromotion();
}

2. 支付策略

//抽象策略
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);
}
//支付宝
public class AliPay extends Payment {
    public String getName() {
        return "支付宝";
    }
    protected double queryBalance(String uid) {
        return 900;
    }
}
//微信
public class WechatPay extends Payment {
    public String getName() {
        return "微信支付";
    }
    protected double queryBalance(String uid) {
        return 263;
    }
}
//京东
public class JDPay extends Payment {
    public String getName() {
        return "京东白条";
    }
    protected double queryBalance(String uid) {
        return 500;
    }
}
//银联
public class UnionPay extends Payment {
    public String getName() {
        return "银联支付";
    }
    protected double queryBalance(String uid) {
        return 120;
    }
}
//上下文
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 UNION_PAY = "UnionPay";
    public static  final String DEFAULT_PAY = ALI_PAY;

    private static Map<String,Payment> strategy = new HashMap<String,Payment>();

    static {
        strategy.put(ALI_PAY,new AliPay());
        strategy.put(JD_PAY,new JDPay());
        strategy.put(WECHAT_PAY,new WechatPay());
        strategy.put(UNION_PAY,new UnionPay());
    }

    public static Payment get(String payKey){
        if(!strategy.containsKey(payKey)){
            return strategy.get(DEFAULT_PAY);
        }
        return strategy.get(payKey);
    }
}
//消息
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 + ‘\‘‘ +
                ‘}‘;
    }
}
//订单
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);
    }
}
//调用
public class Test {
    public static void main(String[] args) {
        Order order = new Order("1","2020031401000323",324.5);
        System.out.println(order.pay(PayStrategy.UNION_PAY));
    }
}

策略模式的优点

1、符合开闭原则

2、避免多重条件转移语句

3、提高算法的保密性和安全性

策略模式的缺点

1、客户端必须知道所有的策略,并且自行决定适用哪一个策略类

2、代码种会产生非常多策略类,增加维护难度

二、责任链模式

1、责任链模式 [Chain of Responsibility Pattern] 是将链中每一个节点看作是一个对象,每个节点处理的请求均不同,且内部自动维护一个下一节点对象。

2、当一个请求从链式的首端发出时,会沿着链的路径依次传递给每一个节点对象,甚至有对象处理这个请求为止

3、属于《行为型模式》

【适用场景】

1、多个对象可以处理同意请求,但是具体由哪个对象处理则再运行时动态决定

2、在不明确指定接收者的情况下,向多个对象种的一个提交一个请求

3、可动态指定一组对象处理请求

1. 代码展示

//对象
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;
    }

    @Override
    public String toString() {
        return "Member{" +
                "loginName=‘" + loginName + ‘\‘‘ +
                ", loginPass=‘" + loginPass + ‘\‘‘ +
                ", roleName=‘" + roleName + ‘\‘‘ +
                ‘}‘;
    }
}
//抽象处理器
public abstract class Handler {
    protected Handler next;//下一个,传播
    public void next(Handler next){ this.next = next;}
    public abstract void doHandler(Member member);
}
//校验处理器
public class ValidateHandler extends Handler {
    public void doHandler(Member member) {
        if(StringUtils.isEmpty(member.getLoginName()) ||
                StringUtils.isEmpty(member.getLoginPass())){
            System.out.println("用户名和密码为空");
            return;
        }
        System.out.println("用户名和密码不为空,可以往下执行");
        next.doHandler(member);
    }
}
//登录处理器
public class LoginHandler extends Handler {
    public void doHandler(Member member) {
        System.out.println("登录成功!");
        member.setRoleName("管理员");
        next.doHandler(member);
    }
}
//权限处理器
public class AuthHandler extends Handler {
    public void doHandler(Member member) {
        if(!"管理员".equals(member.getRoleName())){
            System.out.println("您不是管理员,没有操作权限");
            return;
        }
        System.out.println("允许操作");
    }
}
//传起来
public class MemberService {
    public void login(String loginName,String loginPass){
        Handler validateHandler = new ValidateHandler();
        Handler loginHandler = new LoginHandler();
        Handler authHandler = new AuthHandler();

        validateHandler.next(loginHandler);
        loginHandler.next(authHandler);

        validateHandler.doHandler(new Member(loginName,loginPass));
    }
}
//调用
public static void main(String[] args) {
    MemberService memberService = new MemberService();
    memberService.login("tom","666");
}

1、总是调用next(),next()太多容易混乱
2、加入建造者模式来优化

2. 优化

//抽象处理器
public abstract class Handler<T> {
    protected Handler next;
    public void next(Handler next){ this.next = next;}

    public abstract void doHandler(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;
                }
                this.tail.next(handler);
                this.tail = handler;
//            }while (false);//真正框架中,如果是双向链表,会判断是否已经到了尾部
            return this;
        }
        public Handler<T> build(){
            return this.head;
        }
    }
}
//service代码优化
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().doHandler(new Member(loginName,loginPass));

}

责任链模式的优点:

1、将请求与处理解耦

2、请求处理者 [节点对象] 只需关注自己感兴趣的请求进行处理即可,对于不感兴趣的请求,直接转发给下一级节点对象

3、具备链式传递处理请求功能,请求发送这无需知晓链路结构,只需等待请求处理结果

4、链路结构灵活,可以通过改变链路结构动态的新增或删除责任

5、易于扩展薪的请求处理类 [节点],符合开闭原则

责任链模式的缺点:

1、责任链太长或者处理时间过长,会影响整体性能

2、如果节点对象存在循环引用时,会造成死循环,导致系统崩溃

11. 策略模式与责任连模式

原文:https://www.cnblogs.com/JustDoIt-1221/p/14597948.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!