专栏首页bingfeng-技术设计模式之 - 策略落实

设计模式之 - 策略落实

一、什么是策略模式

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

我们来看下策略模式的UML图:

二、策略模式的构成

  • 公共策略:定义一个接口作为公共策略,所有的算法规则实现该接口;
  • 具体策略:封装了具体的算法和行为,继承于公共策略;
  • 封装类:进行二次封装,维护对公共策略对象的引用;

三、实例演示

业务场景:现在我们在做一个商场的优惠活动,这个活动根据节日的不同也会调整相应的活动规则,比如五一黄金周我们是所有会员商品一律8折,节日过后恢复原价不再优惠,等到了国庆商场有有了新的促销活动,满300减150,那么根据这样的业务需求我们来看看使用策略模式到底应该怎么做?

首先我们需要创建一个公共的策略类

public interface Strategy {

    // 算法规则
    double regulation(double money);
}

接下来我们分别定义三种活动规则,首先是没有优惠活动的收费方式

public class NormalStrategy implements Strategy {

    @Override
    public double regulation(double money) {

        System.out.println("正常收费 : " + money);
        return money;
    }
}

打折

public class DiscountStrategy implements Strategy {

    private double moneyDiscount = 1D;

    public DiscountStrategy(String discount) {

        this.moneyDiscount = Double.parseDouble(discount);
    }

    @Override
    public double regulation(double money) {

        System.out.println("打折优惠 : " + money * moneyDiscount);
        return money * moneyDiscount;
    }
}

满300返150

public class RebateStrategy implements Strategy {

    // 满多少
    private double moneyCondition = 0.0D;

    // 减多少
    private double moneyRebate = 0.0D;

    public RebateStrategy(String moneyCondition, String moneyRebate) {

        this.moneyCondition = Double.parseDouble(moneyCondition);
        this.moneyRebate = Double.parseDouble(moneyRebate);
    }

    @Override
    public double regulation(double money) {

        // 判断是否满足返利条件
        if (money > moneyCondition) {

            System.out.println("折扣返现 : " + (money - Math.floor(money / moneyCondition) * moneyRebate));
            return money - Math.floor(money / moneyCondition) * moneyRebate;
        }

        System.out.println("不够返现条件 : " + money);
        return money;
    }
}

接下来,我们需要创建一个封装类也可以叫上下文的类,对我们的活动规则进行一个维护

public class Context {

    private Strategy strategy;

    public Context(String type,double money) {

        switch (type) {

            case "正常收费":
                Strategy normalStrategy = new NormalStrategy();
                strategy = normalStrategy;
                strategy.regulation(money);
                break;

            case "打5折":
                Strategy discountStrategy = new DiscountStrategy("0.5");
                strategy = discountStrategy;
                strategy.regulation(money);
                break;

            case "满300减150":
                Strategy rebateStrategy = new RebateStrategy("300", "150");
                strategy = rebateStrategy;
                strategy.regulation(money);
                break;
        }
    }
}

最后我们分别来测试看下结果是否正确:

public class Main {

    public static void main(String[] args) {

        new Context("打5折", 500);

        new Context("正常收费", 500);

        new Context("满300减150", 500);
    }
}

可能有读者就存在疑问了,这跟简单工厂模式又有什么区别呢?

第一:首先在我们的封装类中其实已经使用到了简单工厂模式,我们使用简单工厂模,我们通过这种方式的封装将判断是什么优惠的过程从客户端转移到了我们的程序中,客户不需要再去关系;

第二:我们来看下我们昨天的简单工厂模式客户端事怎么调用的,再来看看我们今天使用策略模式是怎么调用的

通过上面我们可以看到,简单工厂模式需要客户端认识两个类,也就是CarFactory和Product,而简单工厂模式只需要客户端认识一个类,也就是Context,这样就降低了我们代码的耦合性。

四、策略模式的优点

  • 策略模式之间可以自由的切换;
  • 增加了程序的扩展性,如果想要增加新的策略,只需要实现公共的策略即可;
  • 避免使用多重条件,当所有的算法都堆积在一个类中,那么就不可避免的要使用条件判断来选择合适的算法;

五、策略模式的缺点

  • 如果有新的策略确实很容易进行扩展,但是当策略多了之后维护就变得比较艰难,所以一般策略的数量一般维护在3个左右;
  • 必须把所有的策略暴露给用户,用户好知道知道使用哪种策略;

本文分享自微信公众号 - 一个程序员的成长(xiaozaibuluo),作者:一个程序员的成长

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2018-11-02

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • RabbitMQ工作队列之公平分发消息与消息应答(ACK)

    上篇文章中,我们讲了工作队列轮询的分发模式,该模式无论有多少个消费者,不管每个消费者处理消息的效率,都会将所有消息平均的分发给每一个消费者,也就是说,大家最后各...

    一个程序员的成长
  • 设计模式之 - 装饰者模式

    装饰着模式:简单的一句话理解就是,动态的给一个对象添加一些额外的功能,装饰者模式相对于生成子类更加的灵活。

    一个程序员的成长
  • @PostConstruct注解,你该好好看看

    做过微信或支付宝支付的童鞋,可能遇到过这种问题,就是填写支付结果回调,就是在支付成功之后,支付宝要根据我们给的地址给我们进行通知,通知我们用户是否支付成功,如果...

    一个程序员的成长
  • 最大信息系数(MIC)

    MIC(Maximal information coefficient)一个很神奇的东西,源自于2011年发在sicence上的一个论文。

    钱塘小甲子
  • 【对话】京东基础架构部高级软件开发工程师张墨飞:全面解读京东ForceBot全链路压测平台技术核心

    ? 张墨飞 基础架构部高级软件开发工程师 京东技术11.11基础架构峰会讲师 电商大促准备好的第一件事情就是应对高流量,全链路压测无疑成为必不可少的一个环节...

    京东技术
  • 解决matplotlib.pyplot在Jupyter notebook中不显示图像问题

    看莫烦老师的matplotlib教程中,有一段sinx函数动画,用Jupyter跑却不能显示动画效果。

    砸漏
  • java并发包(1)-AtomicReference和AtomicStampedReference

    AtomicReference原子应用类,可以保证你在修改对象引用时的线程安全性,比较时可以按照偏移量进行

    yiduwangkai
  • Java基础篇(01):基本数据类型,核心点整理

    不使用New创建,声明一个非引用传递的变量,且变量的值直接置于堆栈中,大小不随运行环境变化,效率更高。使用new创建的引用对象存储在堆中。

    知了一笑
  • 【Java_17】Lambda 表达式

    用户8250147
  • JAVA-基础语法以及String的介绍

    J2SE:Java 2 Platform Standard Edition(2005年之后更名为JAVA SE)。

    张诺谦

扫码关注云+社区

领取腾讯云代金券