[设计模式] - 策略模式 多算法选择的福音

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

策略模式的结构

  • 封装类:也叫上下文,对策略进行二次封装,目的是避免高层模块对策略的直接调用。
  • 抽象策略:通常情况下为一个接口,当各个实现类中存在着重复的逻辑时,则使用抽象类来封装这部分公共的代码,此时,策略模式看上去更像是模版方法模式。
  • 具体策略:具体策略角色通常由一组封装了算法的类来担任,这些类之间可以根据需要自由替换。

策略模式的适用场景

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

使用策略模式实现支付方式

大家在网购中经常会碰到优惠活动,有使用优惠券满199-100返现活动等,而这些不一样的优惠方式就可以用上策略模式。

首先,我们定义一个促销优惠的抽象类PromotionStrategy,在其中定义一个促销方法,让所有具体的策略都继承这个类。

public interface PromotionStrategy {
    void doPromotion();
}

之后使用优惠券(CouponStrategy())和返现(CashbackStrategy())作为促销的实现类

public class CouponStrategy implements PromotionStrategy {
    @Override
    public void doPromotion() {
        System.out.println("优惠券抵扣策略");
    }
}
public class CashbackStrategy implements PromotionStrategy {
    @Override
    public void doPromotion() {
        System.out.println("返现策略");
    }
}

最后,定义一个策略的封装类PromotionActivity

public class PromotionActivity {

    private PromotionStrategy promotionStrategy;

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

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

这样我们就可以测试一下效果,通过传入不同策略来运行。

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

    String promotionKey = "coupon";

    if (promotionKey.equals("coupon")){
        promotionActivity = new PromotionActivity(new CouponStrategy()) ;
    }else if (promotionKey.equals("cashback")){
        promotionActivity = new PromotionActivity(new CashbackStrategy()) ;
    }
    promotionActivity.execute();
}

这样我们可以通过不同的需要来选择不同的优惠策略。但是,经过一段时间的业务积累,我们的促销活动越来越多,每次都要修改大量代码和测试,判断也变得越来越复杂。这时我们的代码就该重构了,我们通过之前学过的单例模式工厂模式对代码进行改造。
下面我们加入一个促销工厂类PromotionStrategyFactory,创建一个map来维护我们的促销策略,通过getPromotionStrategy(String promotionKey)方法获取到具体的策略。

public class PromotionStrategyFactory {

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

    static {
        PROMOTION_STRATEGY_MAP.put("coupon",new CouponStrategy());
        PROMOTION_STRATEGY_MAP.put("cashback",new CashbackStrategy());
    }

    private PromotionStrategyFactory(){}

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

而这时,我们的测试类也应该修改一下了。

public class Test {

    public static void main(String[] args) {
        PromotionStrategy p = PromotionStrategyFactory.getPromotionStrategy("coupon");

        PromotionActivity pa = new PromotionActivity(p);

        pa.execute();
    }
}

这样我们每次上新活动之后就不用影响之前代码的逻辑,只需在map中加入新促销活动即可。

策略模式的优缺点

优点:

  1. 策略模式符合开闭原则
  2. 避免使用大量判断语句
  3. 使用策略模式可以提高算法的保密性和安全性
    缺点:
  4. 客户端必须知道所有策略,并且自己觉得使用策略
  5. 代码产生很多策略类,增加维护难度
    原文作者:MarchZhen
    原文地址: https://blog.csdn.net/wuskzuo/article/details/89062263
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞