策略模式定义与实现

策略模式的定义

​ 首先我们可以先看一下策略模式的定义:

Define a family of algorithms,encapsulate each one,and make them interchangeable.(定义一组算法,将每个算法都封装起来,并且使它们之间可以互换。)

​ 这个定义是非常明确、清晰的,“定义一组算法”,同一个接口的不同实现类是不是三个算法?“将每个算法都封装起来”,封装类Context不就是这个作用吗?**“使它们可以互换”**当然可以互换了,都实现是相同的接口,那当然可以相互转化了。

​ 下面简单的总结一下,就是我们有一个接口(也可以是抽象类),这个接口有不同的实现类,每一个实现类就是一个策略,并且这里还有一个封装类Context,这个封装类里面就是封装了不同的策略,我们对于策略的调用就是通过这个封装类去执行的。

策略模式的通用类图

​ 下面我们再看一下责策略模式定义的通用的类图是什么样子的。

​ 策略模式使用的就是面向对象的继承和多态机制,非常容易理解和掌握,我们再来看看策略模式的三个角色:

Context封装角色

​ 它也叫做上下文角色,起承上启下封装作用,屏蔽高层模块对策略、算法的直接访问,封装可能存在的变化。

Strategy抽象策略角色

​ 策略、算法家族的抽象,通常为接口,定义每个策略或算法必须具有的方法和属性。各位看官可能要问了,类图中的AlgorithmInterface是什么意思,嘿嘿,algorithm是“运算法则”的意思,结合起来意思就明白了吧。

ConcreteStrategy具体策略角色

​ 实现抽象策略中的操作,该类含有具体的算法。

策略模式的通用代码

​ 下面我们可以看一下《设计模式之禅》中讲到的通用代码实现:

抽象策略角色(Strategy)

public interface Strategy { //策略模式的运算法则 public void doSomething();
}

具体策略角色(ConcreteStrategy)

​ 具体策略也是非常普通的一个实现类,只要实现接口中的方法就可以,伪代码实现我们可以参考如下:

// 具体策略1
public class ConcreteStrategy1 implements Strategy { public void doSomething() { System.out.println("具体策略1的运算法则"); }
}// 具体策略2
public class ConcreteStrategy2 implements Strategy {public void doSomething() { System.out.println("具体策略2的运算法则"); }
}

封装角色(Context)

​ 策略模式的重点就是封装角色,它是借用了代理模式的思路,这里我们也可以思考一下,它和代理模式有什么差别,差别就是策略模式的封装角色和被封装的策略类不用是同一个接口,如果是同一个接口那就成为了代理模式。

public class Context { // 抽象策略 private Strategy strategy = null;// 构造函数设置具体策略 public Context(Strategy _strategy) { this.strategy = _strategy; }// 封装后的策略方法 public void doAnythinig() { this.strategy.doSomething(); }
}

高层调用(Client)

​ 这里模拟我们调用策略,一般就是直接调用我们的封装角色,实现解耦的特性。

public class Client { public static void main(String[] args) { // 声明一个具体的策略 Strategy strategy = new ConcreteStrategy1(); // 声明上下文对象 Context context = new Context(strategy); // 执行封装后的方法 context.doAnythinig(); }
}

实战-策略模式实现优惠券

优惠券业务逻辑说明

​ 这里为了方便大家对策略模式的理解,我这里举例的优惠券的场景是非常简单的一种,实际工作中肯定比这个复杂的多,所以请不要介意细节性的东西,只是为了方便我们去结合一些适用的场景去理解策略模式。

​ 下面说一下我们的优惠券业务场景是,我们有一个优惠券活动,这个活动有两种:满减优惠券(满100减10、满200减30、满500减80)、折扣优惠券(8折优惠)两种。

策略模式实现优惠券功能流程图

​ 这里面由于优惠券活动有两种优惠券类型,一个是满减优惠券,一个是折扣优惠券,所以我这里就设计了一个优惠券策略接口(CouponStrategy)以及两个具体策略(DiscountCoupon和FullMinusCoupon)折扣优惠券和满减优惠券,还有非常关键的角色就是我们的策略封装角色Context,里面的内容主要是用来封装我们的策略对象。

策略模式实现优惠券功能代码实现

​ idea中代码设计的diagram类图如下所示:

CouponStrategy.java(优惠券策略接口)

import java.math.BigDecimal;/*** @author gcc* @version 1.0* @ClassName ActiveStrategy* @description 优惠券策略接口* @date 2021/9/30 9:20*/
public interface CouponStrategy {/*** 优惠券策略* @author gcc* @date  2021/9/30 9:21*/void doActive(BigDecimal money);
}

DiscountCoupon.java(折扣优惠券具体策略)

import java.math.BigDecimal;
import java.text.DecimalFormat;/*** @author gcc* @ClassName DiscountCoupon 折扣优惠券* @description 折扣优惠券* @date 2021/9/30 9:23*/
public class DiscountCoupon implements CouponStrategy {/*** 折扣优惠券** @author gcc* @date 2021/9/30 9:24*/@Overridepublic void doActive(BigDecimal money) {// 8折优惠券DecimalFormat decimalFormat =new DecimalFormat("#.00");System.out.println("折后优惠价:" + decimalFormat.format(money.multiply(new BigDecimal(0.8d))));}
}

FullMinusCoupon.java(满减优惠券具体策略)

import java.math.BigDecimal;/*** @author gcc* @version 1.0* @ClassName FullMinusCoupon* @description 满减优惠券* @date 2021/9/30 9:34*/
public class FullMinusCoupon implements CouponStrategy {@Overridepublic void doActive(BigDecimal money) {Double sourceMoney = money.doubleValue();if (sourceMoney < 100) {// 不满减System.out.println("没有满减 原价:" + sourceMoney);} else if (sourceMoney < 200) {// 满100减10System.out.println("满100减10 优惠后:" + (sourceMoney - 10));} else if (sourceMoney < 500) {// 满200减30System.out.println("满200减30 优惠后:" + (sourceMoney - 30));} else {// 满500减80System.out.println("满500减80 优惠后:" + (sourceMoney - 80));}}
}

CouponContext.java(优惠券封装角色)

import java.math.BigDecimal;/*** @author gcc* @version 1.0* @ClassName CouponContext* @description 优惠券转换角色Context* @date 2021/9/30 9:39*/
public class CouponContext {private CouponStrategy couponStrategy;public CouponContext(CouponStrategy couponStrategy) {this.couponStrategy = couponStrategy;}void execute(BigDecimal money) {couponStrategy.doActive(money);}
}

ConponClient.java (调用优惠券活动)

import java.math.BigDecimal;/*** @author gcc* @version 1.0* @ClassName ConponMain* @description 高层模块调用的优惠券活动* @date 2021/9/30 9:40*/
public class ConponClient {public static void main(String[] args) {// 打折价格券活动CouponContext dispatcher = new CouponContext(new DiscountCoupon());dispatcher.execute(new BigDecimal(300d));// 满减优惠券活动CouponContext fullMinusCoupon = new CouponContext(new FullMinusCoupon());fullMinusCoupon.execute(new BigDecimal(300d));}
}

总结

​ 整体来说策略模式还是比较简单的,就是我们常规理解的面向对象多态的特性,一个接口多个实现的方式,只不过多了一个封装对象而已。当然真正工作当中的业务逻辑肯定没有这么简单,这里仅仅是让我们了解到策略模式到底是什么样子的,仅仅是我们了解设计模式的前期基础阶段。

设计模式-优惠券-策略模式相关推荐

  1. Java设计模式之策略模式与状态模式

    一.策略模式定义 定义:策略模式定义了一系列的算法,并将每一个算法封装起来,而且使他们之间可以相互替换,策略模式可以在不影响客户端的情况下发生变化. 好了,定义看看就完了,我知道你很烦看定义. 二.策 ...

  2. 换个姿势学设计模式:策略模式

    点击上方蓝色"程序猿DD",选择"设为星标" 回复"资源"获取独家整理的学习资料! 来源:公众号「闻人的技术博客」 前言 前段时间,接到一个 ...

  3. 研磨设计模式之 策略模式--转

    http://www.uml.org.cn/sjms/201009092.asp 研磨设计模式之 策略模式   2010-09-09 作者:云飞龙行 来源:云飞龙行的blog   先感谢众多朋友的支持 ...

  4. 设计模式:策略模式(Strategy)

    定   义:它定义了算法家族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化, 不会影响到使用算法的客户. 示例:商场收银系统,实现正常收费.满300返100.打8折.......等不同收费 ...

  5. C++设计模式之策略模式(Strategy)

    Strategy策略模式 作用:定义了算法家族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化,不会影响到使用算法的客户. UML图: 代码实现 #include <iostream& ...

  6. python策略模式包含角色_详解Python设计模式之策略模式

    虽然设计模式与语言无关,但这并不意味着每一个模式都能在每一门语言中使用.<设计模式:可复用面向对象软件的基础>一书中有 23 个模式,其中有 16 个在动态语言中"不见了,或者简 ...

  7. 一篇博客读懂设计模式之-----策略模式

    设计模式之策略模式 在策略模式中,我们创建表示各种策略的对象和一个行为随着策略对象改变而改变的对象 定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换. 主要解决:在有多种算法相似的情况下 ...

  8. 面向对象设计模式之策略模式

    面向对象设计模式之策略模式 1.策略模式定义了算法族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化独立于使用算法的客户 2.抽象鸭子类,鸭子飞行行为在此处类似于算法族 1 package ...

  9. java策略模式详解_Java经典设计模式之策略模式原理与用法详解

    本文实例讲述了Java经典设计模式之策略模式.分享给大家供大家参考,具体如下: 策略模式指:策略模式指将程序中可变部分抽象分离成一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换.策略模式 ...

最新文章

  1. 代码之谜(二)- 语句与表达式
  2. python基础教程:懒惰属性(延迟初始化)
  3. py---------面向对象进阶
  4. CDATA和转义字符
  5. python相对路径找不到文件_Python相对路径从子文件夹导入
  6. mysql aes密钥大于16位_aes秘钥限制问题解决办法
  7. matlab经纬度画二维图,Matlab绘制汉经纬度的散点图 2
  8. elementUI 日期选择控件少一天的问题解决方法
  9. java constants无法使用_轻松看懂Java字节码
  10. marven编译时:<pre>错误: 不允许使用自关闭元素</pre>
  11. 八个小技巧教你做出舒服的MG动画
  12. Microsoft Dynamics NAV成本原理讲解
  13. [python]excel试题转为json,并生成
  14. vue 响应式布局组件_今天如何使用响应式Web组件
  15. 通信加密原理(对称密钥、公钥、私钥)
  16. Java并发编程--线程池ThreadPollExecutor原理探究
  17. 详细地址通过正则抽取省市区
  18. C#窗体Click事件没反应
  19. 【信号分析之心电信号处理】
  20. Python tkinter 学习笔记(2)-- 控件、组件(二)

热门文章

  1. 计算机数字媒体专业毕业论文,数字媒体艺术专业毕业论文
  2. 移动互联应用开发基础知识简答
  3. 【MFC】数据库操作——ODBC(20)
  4. 再论推翻百年集论的真扩集定理(2165字)
  5. 如何快速提升网站排名流量
  6. MySQL趋势与前景技术分享
  7. 2009年计算机统考考研试题及参考答案
  8. 【软件测试】300个不得不懂的理论知识(上)
  9. MATLAB-编程入门
  10. Casbin get-users 账号密码泄漏漏洞