策略模式

 

学习了一下策略模式,秉着好记性不如烂笔头的耿直,记录并分享给大家,望同学们一键三连!!!

直接进入主题:

策略模式的官方定义:

将定义的算法家族分别封装起来,让他们之间可以互相替换,从而让算法的变化不会影响到使用算法的用户。

策略模式使用的就是面向对象的继承和多态机制,从而实现一个行为在不同场景下具备不同的实现。

策略模式的应用场景

1. 阶梯个税:不同的税率对应不用的处理方式

2. 支付方式的选择:不同的支付方式对应不同的渠道

策略模式可以解决在有多种相似算法的情况下使用if...else或者swith...case所带来的复杂性和臃肿性的问题,主要适用于:

(1)针对同一类型问题,有多种处理方式,每一种都能独立解决问题。

(2)需要自由切换算法的场景。

(3)需要屏蔽算法规则的场景。

UML类图

由上图可以看到,策略模式主要包含3部分

  1. 角色调度层:用来操作所需要的的上下文环境,屏蔽高层模块(客户端对策略、算法的直接访问),封装可能存在的变化
  2. 抽象策略角色(IPromotionStrategy):规定策略或算法的行为
  3. 具体的策略角色:具体的策略或者算法实现

最简单的策略模式写法

public class Client {
    /**
     * 抽象策略类
     */
    interface IStrategy{
        void algorithm();
    }

    static class ConCreateStrategyA implements IStrategy{

        @Override
        public void algorithm() {
            System.out.println("Strategy A");
        }
    }

    static class ConCreateStrategyB implements IStrategy{

        @Override
        public void algorithm() {
            System.out.println("Strategy B");
        }
    }

    /**
     * 调度算法
     */
    static class Context{
        private final IStrategy strategy;

        public Context(IStrategy iStrategy){
            this.strategy = iStrategy;
        }
        public void algorithm(){
            this.strategy.algorithm();
        }
    }


    public static void main(String[] args) {
        // 生成一个具体策略
        IStrategy strategy = new ConCreateStrategyA();
        // 创建一个环境
        Context context = new Context(strategy);
        // 执行算法
        context.algorithm();
    }
}

解决实现问题

一个方案的实现主要是为了解决实际中发生的问题,来看一个促销的例子.

场景:淘宝活动优惠打折,优惠策略有很多种可能,如领取优惠券抵扣、返现促销、拼团优惠等。

首先创建促销实例的抽象

/**
 * 促销策略抽象
 */
public interface IPromotionStrategy {
    void doPromotion();
}

然后分别创建具体的优惠方案

优惠券抵扣方案:

public class CouponStrategy implements IPromotionStrategy {
    @Override
    public void doPromotion() {
        System.out.println("使用优惠券抵扣");
    }
}

返现促销: 

public class CashbackStrategy implements IPromotionStrategy {
    @Override
    public void doPromotion() {
        System.out.println("返现,直接打款");
    }
}

拼团优惠:

public class GroupbuyStrategy implements IPromotionStrategy {
    @Override
    public void doPromotion() {
        System.out.println("5人成团,可以优惠");
    }
}

无优惠:

public class EmptyStrategy implements IPromotionStrategy {
    @Override
    public void doPromotion() {
        System.out.println("无优惠");
    }
}

我们来创建一个实际的策略调度层

/**
 * 促销活动方案
 */
public class PromotionActivity {

    private final IPromotionStrategy iPromotionStrategy;

    public PromotionActivity(IPromotionStrategy iPromotionStrategy){
        this.iPromotionStrategy = iPromotionStrategy;
    }
    public void execute(){
        iPromotionStrategy.doPromotion();
    }

}

调度层代码就写好了,那整个策略模式的实现就基本上完成了,下面我们来看一下如何使用,看客户端的测试代码

PromotionActivity promotion = null;
String key = args[0];
if(Objects.equals(key, "COUPON")){
  promotion = new PromotionActivity(new CouponStrategy());
}else if(Objects.equals(key, "CASHBACK")){
  promotion = new PromotionActivity(new CashbackStrategy());
}
promotion.execute();

放到实际的业务场景中,完全能够满足业务场景,但是大家觉得有什么问题呢? 随着业务高速发展,各种优惠券铺天盖地的来,于是,程序员就开始经常加班,每次上活动之前都要通宵改代码,而且要做重复测试,判断逻辑可能也会变得越来越复杂。此时,我们要思考代码是否需要重构。我们来一起看下,利用单例和简单工厂模式,创建PromotionStrategyFactory类

public class PromotionStrategyFactory {

    private static final IPromotionStrategy DEFAULT =  new EmptyStrategy();

    private static Map<String, IPromotionStrategy> PROMOTIONS = new HashMap<>();

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

    public static IPromotionStrategy getStrategy(String key){
        IPromotionStrategy strategy = PROMOTIONS.get(key);
        return strategy==null?DEFAULT:strategy;
    }
    private interface PromotionKey{
        String COUPON = "COUPON";
        String CASHBACK = "CASHBACK";
        String GROUPBUY = "GROUPBUY";
    }

}

完成后,我们再看客户端测试代码:

String promotionKey = args[0];
IPromotionStrategy strategy = PromotionStrategyFactory.getStrategy(promotionKey);
strategy.doPromotion();

这样就简洁了很多,也充分体现了我们使用设计模式的目的。最终程序员也不再加班了。

 

Attention

上面是利用了接口来实现的策略模式,大家的思维不要仅仅局限于implements接口,开篇就说过,策略模式使用的就是面向对象的继承和多态机制。这里就不再赘述,原理都是一样。

缺点

人无完人,每种设计模式也是在特定的场景下才能发挥出最佳的效果,滥用设计模式必将为以后的加班埋下祸根。那我们来看看策略模式的缺点:

  1. 客户端必须知道所有的策略,并且自行决定使用哪一个策略类。
  2. 代码中会产生非常多策略类,增加维护难度。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

周润发的弟弟

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

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

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

打赏作者

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

抵扣说明:

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

余额充值