设计模式学习(六)策略模式

定义

策略模式(Strategy Pattern)是指定义了算法家族,将算法逻辑分别封装起来,让他们之间可以相互替换,让算法的变化不会影响到使用算法的用户。

可以避免多重分支的if…else…和switch语句。

应用场景

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

案例一: 针对订单的不同支付方式

UML类图

在这里插入图片描述

代码实现

Order 类

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

MsgResult 类

public class MsgResult {

    private Integer code;
    private String msg;
    private Object data;

    public MsgResult(Integer code, String msg, Object data) {
        this.code = code;
        this.msg = msg;
        this.data = data;
    }

    @Override
    public String toString() {
        return "支付状态:[" + code + "]," + msg +
                ",交易详情:" + data;
    }
}

PayStrategy 类

public class PayStrategy {

    /**
     * 事先已知各种支付类型
     */
    public static final String ALI_PAY = "Alipay";
    public static final String JD_PAY = "Jdpay";
    public static final String UNION_PAY = "UnionPay";
    public static final String Wechat_PAY = "WechatPay";
    public static final String DEFAULT_PAY = ALI_PAY;

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

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

    /**
     * 通过统一入口实现动态策略
     *
     * @param payKey
     * @return
     */
    public static Payment get(String payKey) {
        if (!payStrategy.containsKey(payKey)) {
            return payStrategy.get(DEFAULT_PAY);
        }
        return payStrategy.get(payKey);
    }
}

Payment 类

public abstract class Payment {

    /**
     * 获取支付方式名称
     */
    public abstract String getName();

    /**
     * 获取余额
     */
    protected abstract double queryBalance(String uid);

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

AliPay 类

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

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

JDPay 类

public class JDPay extends Payment {

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

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

UnionPay 类

public class UnionPay extends Payment {

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

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

WechatPay 类

public class WechatPay extends Payment {

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

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

测试类

public class StrategyTest {
    public static void main(String[] args) {
        Order order = new Order("1", "2019111900000009", 324.45);

        MsgResult msg = order.pay(PayStrategy.ALI_PAY);
        System.out.println(msg);
    }
}

输出结果

欢迎使用支付宝
本次交易金额为:324.45,开始扣款....
支付状态:[200],支付成功,交易详情:支付金额:324.45

案例二: 针对促销的不同优惠活动

UML类图

在这里插入图片描述

代码实现

PormotionActivity 类

public class PromotionActivity {

    /**
     * 促销策略
     */
    private PromotionStrategy promotionStrategy;

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

    public void excute() {
        promotionStrategy.doPromotion();
    }
}

PromotionStrategyFactory 类 (简单工厂模式)

public class PromotionStrategyFactory {

    /**
     * 事前已知各种促销策略
     */
    private static Map<String, PromotionStrategy> PROMOTION_STRATEGY_MAP = new HashMap<>();

    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 static final PromotionStrategy NON_PROMOTION = new EmptyStrategy();

    public 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";
    }

}

PromotionStrategy 类

public interface PromotionStrategy {

    /**
     * 促销
     */
    void doPromotion();
}

CashBackStrategy 类

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

CouponStrategy 类

public class CouponStrategy implements PromotionStrategy {

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

EmptyStrategy 类

public class EmptyStrategy implements PromotionStrategy {

    @Override
    public void doPromotion() {
        System.out.println("无优惠活动");
    }
}

GroupBuyStrategy 类

public class GroupBuyStrategy implements PromotionStrategy {

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

在源码中的体现

Comparator接口的compare()方法, 就是一个策略抽象的实现:

public interface Comparator<T> { 
    int compare(T o1, T o2);
    ... 
}

Comparator抽象西面有飞铲过的实现类, 我们经常把Comparator作为参数传入作为排序策略,

例如Arrays类的parallelSort()方法:

public class Arrays { 
    ... 
    public static <T> void parallelSort(T[] a, int fromIndex, int toIndex, Comparator<? super T> cmp) { 
        ... 
    }
    ... 
}

还有TreeMap 的构造方法:

public class TreeMap<K,V> extends AbstractMap<K,V> implements NavigableMap<K,V>, Cloneable, java.io.Serializable { 
    ...
    public TreeMap(Comparator<? super K> comparator) { 
        this.comparator = comparator;
    }
    ... 
}

优点

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

缺点

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

和其他设计模式的结合

委派模式 + 策略模式

策略模式 + 构造器,如案例一

策略模式 + 简单工厂模式,如案例二

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不愿放下技术的小赵

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值