设计模式之策略模式实战讲解

设计模式之策略模式实战讲解

出发点🚠

其实简单来说策略模式就是:再进行需求变更,业务演化过程时 能够新增代码去实现业务需求的变更 而不修改原来的代码——也就是说其要符合 开闭原则

何为开闭原则🧐

开放封闭原则(OCP,Open Closed Principle)作为设计模式六大原则之一,也是面向对象编程的核心:其本质就是说 :对扩展开放,对修改封闭

演示开闭原则学习👨‍🏭

控制层

 

kotlin

复制代码

@RestController public class CouponController {     @Resource     private CouponService couponService;     @RequestMapping(value = "/getMoney",method = RequestMethod.GET)     public BigDecimal getMoney() {         return couponService.getDiscount();     } }

接口

 

csharp

复制代码

public interface CouponService {      \**      \* 获取优惠券金额      \* @return BigDecimal      \*     BigDecimal getMoney(); }

事务

 

java

复制代码

@Service\ public class CouponInterfaceImpl implements CouponService {     /\*\*\      \* 折扣\      \*/\     private final BigDecimal discount = new BigDecimal("0.5");     @Override\     public BigDecimal getMoney() {\         return new BigDecimal(50).multiply(discount);\     }\ }

以上也是为了举一个例子 :

因为其实大家可能都知道 要定义一个接口 然后一个类去实现它 这样做

但是这样做 的意义是什么 可能大家就不是太清楚啦 只知道:噢!这是一个规范 那么我就应该去遵守它。

It's been a long time……

参加 需求分析评审:

然后你听到产品这样说:首先是一个折扣 再代码刚上线的时候 全场五折!

咔嚓咔嚓 你记下来这个需求~ 这里这样去写的~

然后 写完 你转头继续去写别的需求!

过了两天 说要和用户项目组那边协调 要查看用户的角色 再角色上进行校验

admin 账号 享有 公司员工折扣 vip 享有会员折扣 不充值vip 没有折扣😂~

 

typescript

复制代码

@Service\ public class CouponInterfaceImpl implements CouponService {     \*      \* 默认折扣      \*     private  BigDecimal discount = new BigDecimal("0.5");     @Override     public BigDecimal getMoney(String role) {         // 公司账号 管理员权限 享受员工价         if ("admin".equals(role)) {             discount = new BigDecimal("0.4");             return new BigDecimal(50).multiply(discount);         }         // 开店充值会员 享受 会员价         if ("vip".equals(role)) {             return new BigDecimal(50).multiply(discount);         }         // 其他账号 不参与折扣         return new BigDecimal(50);     } }

然后你的代码 就变成了这样

过了几天 再继续开发

领导又说 不行不行 我们还要这样:

1、如果用户 违规次数 达到了5次 用户账号处于封禁状态 如果封禁状态的用户 无法购买

2、vip 可以进行月内5次 的折扣 svip 可以享受十次折扣 😂😂

然后就变成这样

 

typescript

复制代码

@Service public class CouponInterfaceImpl implements CouponService {      \**      \* 默认折扣      \*     private BigDecimal discount = new BigDecimal("0.5");     @Resource     private CouponMapper couponMapper;     @Override     public BigDecimal getMoney(String role) {         if (!couponMapper.getStatus().equals("1")) {             // todo 打印日志……             return null;         }             // todo 判断用户消费 -> 引入redis mysql             // 公司账号 管理员权限 享受员工价         else {             if ("admin".equals(role)) {                 discount = new BigDecimal("0.4");                 return new BigDecimal(50).multiply(discount);             }         }         // 开店充值会员 才能享受 会员价         if ("vip".equals(role)) {             // 代码逻辑……             return new BigDecimal(50).multiply(discount);         }         // 其他账号 不参与折扣         return new BigDecimal(50);     } }

其实这个时候 代码已经很乱了 正常来说 在上线时前 或者需求提测的时候 会有一个CR环节 也就是说Code Review

然后 你自己优化这段代码 如果你还不了解策略模式的话

可能就是想到的就是简单的 if-else 用一个三目运算符 去优化……

其他代码 比如长 if-else 去通过传入一个type 根据不同的type 比如type 1 为默认方案 type 2 为 xx方案

然后在这个类下 去实现不同的方法 根据type 调用方法

也就是说下面这样:

 

less

复制代码

\**  \* {@code @name} demo  \* {@code @description}  \*  \* @author <a href="https://github.com/lizhe-0423">荔枝程序员</a>  \* {@code @data} 2024 2024/2/3 10:21  \* @Service public class CouponInterfaceImpl implements CouponService {     /\*\*\      \* 默认折扣      \*/\     private final BigDecimal discount = new BigDecimal("0.5");     @Resource     private CouponMapper couponMapper;     @Override     public BigDecimal getMoney(String role) {         if (!couponMapper.getStatus().equals("1")) {             // todo 打印日志……             return null;         }         switch (couponMapper.getType()) {             case 1:                 return getMoneyType1();             case 2:                 return getMoneyType2();             case 3:                 return getMoneyType3();             case 4:                 return getMoneyType4();             default:                 return null;         }     }     public BigDecimal getMoneyType1() {         //默认的策略         return new BigDecimal(50);     }     public BigDecimal getMoneyType2() {         // 拥有vip的用户         return new BigDecimal(25);     }     public BigDecimal getMoneyType3() {         // 拥有admin 用户         return new BigDecimal(20);     }     public BigDecimal getMoneyType4() {         // 其他用户但是为活跃账号         return new BigDecimal(30);     } }

但是 其实这样 我们进行修改的时候还是会去动这个类本身 比如 当上线之后

马上还有一个月双十一

然后你的需求是:

可能会这样 双十一 发送专属双十一的限量10万张折扣券 (0.8折)

1、 折扣券可以和svip会员折扣重叠 但是无法和vip折扣重叠

2、折扣券可以和所有用户参与的专属活动获得的优惠券进行折叠消费

3、……

然后你说:累了毁灭吧 因为要通过封板 及 xx 联调等一系列各种情况 留给你开发时间可能也就 2-3天

当去修改这整个类的时候 就会发现if -else 分支 长到离谱……

策略模式+工厂模式🏹

更改我们的控制层

 

less

复制代码

@RestController public class CouponController {     @Resource     private List<CouponService> couponService;     @RequestMapping(value = "/getMoney", method = RequestMethod.GET)     public BigDecimal getMoney(@RequestParam Integer type) {         if (type==null) {             return null;         }         return Objects.         requireNonNull(couponService.stream().filter(l -> l.isTypeTrue(type)).findFirst().orElse(null)).getMoney();     } }

其实就会发现 不同的实现类去代表着不同的策略

image.png

实现类内部如此定义:

 

typescript

复制代码

@Service public class CouponInterfaceType1Impl implements CouponService {     @Override     public boolean isTypeTrue(Integer type) {         return type == 1;     }     @Override     public BigDecimal getMoney() {         //业务代码         return new BigDecimal(50);     } }

这样 我们在不修改类 方法的同时 通过新增不同实现类 去实现不同的策略功能

演示效果🎨

type 为 1 表示 默认执行策略

image.png

type 为2 表示 会员折扣

image.png

希望本教程能够对大家有所帮助 (●'◡'●)

  • 14
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值