Linux下的设计模式——策略模式(StrategyPattern)深入浅出【建议新手收藏】

一、策略模式简介

策略模式定义:是指定义了算法家族、分别封装起来,让它们之间可以互相替换,此模式让算法的变化不会影响到使用算法的用户

策略模式优点:可以避免多重分支的if…else…和switch语句

策略模式的使用场景

  • 假如系统中有很多类,而他们的区别仅仅在于他们的行为不同。
  • 一个系统需要动态的在几种算法中选择一种。

策略模式案例

JDK中Comparator接口中的int compare(T o1, T o2);方法,在Arrays、TreeMap里可以自定义排序规则

Arrays.class
在这里插入图片描述
TreeMap.class
在这里插入图片描述

  • Spring中的Resource接口
  • Spring中InstantiationStrategy接口,主要对类进行初始化策略,有两个策略实现类,它们不是平级而是继承关系(策略模式中不同策略也可以继承)

CglibSubclassingInstantiationStrategy:Cglib的初始方式
SimpleInstantiationStrategy:JDK的初始化方式

类图
在这里插入图片描述

二、简单代码案例

案例:购买东西有活动时,会有抵用券、返现、拼团等减免金额的策略

优惠策略抽象接口


public interface PromotionStrategy {
    
    

    /**
     * 执行优惠
     */
    void doPromotion();
}

没有优惠

public class EmptyStrategy implements PromotionStrategy{
    
    
    @Override
    public void doPromotion() {
    
    
        System.out.println("无促销活动");
    }
}

抵用券

public class CouponStrategy implements PromotionStrategy {
    
    
    @Override
    public void doPromotion() {
    
    
        System.out.println("领取优惠券,课程的价格直接减去优惠券面值抵扣");
    }
}

返现

public class CashbackStrategy implements PromotionStrategy {
    
    
    @Override
    public void doPromotion() {
    
    
        System.out.println("返现促销,返回的金额转到支付宝账号");
    }
}

拼团

public class GroupBuyStrategy implements PromotionStrategy{
    
    
    @Override
    public void doPromotion() {
    
    
        System.out.println("拼团,满20人成团,全团享受团购价格");
    }
}

优惠活动

public class PromotionActivity {
    
    

    PromotionStrategy promotionStrategy;

    public PromotionActivity(PromotionStrategy promotionStrategy){
    
    
        this.promotionStrategy = promotionStrategy;
    }

    /**
     * 执行优惠活动
     */
    public void execute(){
    
    
        this.promotionStrategy.doPromotion();
    }
}

测试一

public static void main(String[] args) {
    
    
//        618优惠券活动
        PromotionActivity activity618 = new PromotionActivity(new CouponStrategy());
        activity618.execute();
//        双11返现活动
        PromotionActivity activity1111 = new PromotionActivity(new CashbackStrategy());
        activity1111.execute();

    }

测试二

public static void main(String[] args) {
    
    
        PromotionActivity promotionActivity = null;

        String promotionKey = "COUPON";
        if (StringUtils.equals(promotionKey,"COUPON")){
    
    
            promotionActivity = new PromotionActivity(new CouponStrategy());
        }else if (StringUtils.equals(promotionKey,"CASHBACK")){
    
    
            promotionActivity = new PromotionActivity(new CashbackStrategy());
        } // .......

        promotionActivity.execute();
    }

简单实现完发现还可以通过单例模式+简单工厂模式简化代码,用唯一标志选择策略

工厂类

public class PromotionStrategyFactory {
    
    

    private static final Map<String,PromotionStrategy> PROMOTION_STRATEGY_MAP = new ConcurrentHashMap<String,PromotionStrategy>();

    private static final PromotionStrategy NON_PROMOTION = new EmptyStrategy();

    static {
    
    
        PROMOTION_STRATEGY_MAP.put(PromotionKey.COUPON,new CouponStrategy());
        PROMOTION_STRATEGY_MAP.put(PromotionKey.CASHBACK,new CashbackStrategy());
        PROMOTION_STRATEGY_MAP.put(PromotionKey.GROUPBUY,new GroupBuyStrategy());
    }


    private PromotionStrategyFactory(){
    
    }

    public static PromotionStrategy getPromotionStrategy(String promotionKey){
    
    
        PromotionStrategy promotionStrategy = PROMOTION_STRATEGY_MAP.get(promotionKey);
        return promotionStrategy == null ? NON_PROMOTION : promotionStrategy;
    }

    private interface PromotionKey{
    
    
        String COUPON = "COUPON";
        String CASHBACK = "CASHBACK";
        String GROUPBUY = "GROUPBUY";

    }
}

测试

public static void main(String[] args) {
    
    
        String promotionKey = "GROUPBUY";
        PromotionActivity promotionActivity = new PromotionActivity(PromotionStrategyFactory.getPromotionStrategy(promotionKey));
        promotionActivity.execute();
    }

附上类结构图
在这里插入图片描述

三、简单代码二案例

案例:用户下单支付,可以选择多种支付渠道

支付抽象类

public abstract class Payment {
    
    

    /**
     * 支付信息
     * @return
     */
    public abstract String getName();

    /**
     * 余额
     * @param uid
     * @return
     */
    protected abstract double queryBalance(String uid);

    /**
     * 支付
     * @param uid
     * @param amount
     * @return
     */
    public MsgResult pay(String uid,double amount){
    
    
        if (queryBalance(uid) < amount){
    
    
            return new MsgResult(500,"支付失败","余额不足");
        }else {
    
    
            return new MsgResult(200,"支付成功","支付金额: " + amount);
        }
    }
}

支付宝支付

public class AliPay extends Payment{
    
    
    @Override
    public String getName() {
    
    
        return "支付宝";
    }

    @Override
    protected double queryBalance(String uid) {
    
    
        return 900;
    }
}

京东白条

public class JDPay extends Payment{
    
    
    @Override
    public String getName() {
    
    
        return "京东白条";
    }

    @Override
    protected double queryBalance(String uid) {
    
    
        return 500;
    }
}

银联支付

public class UnionPay extends Payment {
    
    
    @Override
    public String getName() {
    
    
        return "银联支付";
    }

    @Override
    protected double queryBalance(String uid) {
    
    
        return 120;
    }
}

微信支付

public class WechatPay extends Payment {
    
    
    @Override
    public String getName() {
    
    
        return "微信支付";
    }

    @Override
    protected double queryBalance(String uid) {
    
    
        return 256;
    }
}

返回消息类

public class MsgResult {
    
    

    private int code;
    private Object data;
    private String msg;

    public MsgResult(int code, Object data, String msg) {
    
    
        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(String payKey){
    
    
        Payment payment = PayStrategy.get(payKey);
        System.out.println("欢迎使用" + payment.getName());
        System.out.println("本次交易金额为:" + amount + ",开始扣款...");
        return payment.pay(uid,amount);
    }

    @Override
    public String toString() {
    
    
        return "Order{" +
                "uid='" + uid + '\'' +
                ", orderId='" + orderId + '\'' +
                ", amount=" + amount +
                '}';
    }
}

支付策略工厂

public class PayStrategy {
    
    

    public static final String ALI_PAY = "AliPay";
    public static final String JD_PAY = "JDPay";
    public static final String WECHAT_PAY = "WchatPay";
    public static final String UNION_PAY = "UnionPay";
    public static final String DEFAULT_PAY = "AliPay";

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

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

    public static Payment get(String payKey){
    
    
        if (!payStrategy.containsKey(payKey)){
    
    
            return payStrategy.get(DEFAULT_PAY);
        }
            return payStrategy.get(payKey);

    }
}

测试

public class PayStrategyTest {
    
    

    public static void main(String[] args) {
    
    
        Order order = new Order("1", "2021110", 1342.45);
        MsgResult result = order.pay(PayStrategy.ALI_PAY);
        System.out.println(result);
    }

}

附上类结构图:
在这里插入图片描述

四、总结

策略模式的优点:

  • 策略模式符合开闭原则。
  • 避免使用多重条件转移语句,如if…else…语句、switch语句。
  • 使用策略模式可以提高算法的保密性和安全性。

策略模式的缺点:

  • 客户端必须知道所有的策略,并且用户自行决定使用哪一个策略类。
  • 代码中会产生非常多策略类,增加维护难度。

还等什么小编推荐自己的linuxC/C++语言交流群:【1106675687】整理了一些个人觉得比较好的学习书籍、视频资料共享在群文件里面,有需要的可以自行添加哦!前100名进群领取,额外赠送一份价值199的C/C++、linux资料包含(视频教程、电子书、实战项目及代码),下面部分展示
在这里插入图片描述
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/m0_50662680/article/details/112474679
今日推荐