设计模式之策略模式_入门

前言

最近接触了优惠券相关的业务,如果是以前,我第一时间想到的就是if_else开始套,这样的话耦合度太高了,如果后期添加或者删除优惠券,必须直接修改业务代码,不符合开闭原则 ,这时候就可以选择我们的**策略模式(Strategy Pattern)**实现解耦,很好的解决上述问题,消除 if-else、switch 多重判断 可以有效应对代码的复杂性,十分优雅!

概念引入

和上期的建造者模式类似,策略模式也有三个重要元素:

  1. 环境类:用于与策略接口交互的类。
  2. 策略接口:定义所有支持的算法的公共接口。
  3. 具体策略类:实现策略接口的具体算法。

具体案例(针对优惠券的案例)

我们都知道不同优惠券有不同的优惠力度,非常契合策略模式本案例将结合策略模式和Spring特性来展示:

1.创建优惠券的策略接口

java 复制代码
/*
* 优惠券就是一个很好的策略模式的案例
* */
public interface DiscountStrategy {
    //优惠券折扣就可以抽象到接口中
    Double discount(Double price);
    //用于标识不同的折扣力度
    String mark();
}

我们通过接口来管理优惠券,内部有负责折扣的抽象方法,具体折扣计算由实现类各自负责;还有负责标识的 mark方法。

2.优惠券的具体实现类

java 复制代码
/*
 * 八折的折扣类,首先要实现之前的折扣接口,然后重写方法
 * 利用Spring的特性,将折扣实现类注入IOC容器
 * */

@Component
public class Discount8Strategy implements DiscountStrategy{
    //8折折扣方法
    @Override
    public Double discount(Double price) {
        return price*0.8;
    }

    @Override
    public String mark() {
        return "1";
    }
}

/*
 * 九折的折扣类,首先要实现之前的折扣接口,然后重写方法
 * 利用Spring的特性,将折扣实现类注入IOC容器
 * */

@Component
public class Discount9Strategy implements DiscountStrategy{
    //9折折扣方法
    @Override
    public Double discount(Double price) {
        return price*0.9;
    }

    @Override
    public String mark() {
        return "2";
    }
}

这里我添加了两种折扣类,分别是8折和9折,同时利用了@Component将二者注入到Spring的IOC容器中,后续将配合Spring完成整个策略模式的实现

3.优惠券工厂+Spring生命周期使用

java 复制代码
/*
 * 这里利用Spring的生命周期,实现InitializingBean方法,在bean初始化这一个阶段做一些处理,实现策略模式
 * */
@Component
public class DiscountStrategyFactory implements InitializingBean {
    //获取到ApplicationContext的实例,可以通过这个获取到想要的类实例
    @Autowired
    private ApplicationContext applicationContext;

    //用来真正存储 (折扣力度标识,对应折扣实例)
    public final HashMap<String,DiscountStrategy> discountStrategies = new HashMap<>();

    //根据标识的mark选择对应的折扣实例,后续可以进行折扣
    public DiscountStrategy chooseDiscount(String mark)
    {
        return discountStrategies.get(mark);
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        //因为到AfterPropertiesSet这个方法的时候,当前Bean的属性已经设置完成,所以我们可以获取到DiscountStrategy接口的实现类
        //利用Map这个数据类型,完成策略模式
        //使用了GetBeansOfType方法直接返回map类型。key是类的名字,value是对应的实例
        Map<String,DiscountStrategy> discountStrategyMap = applicationContext.getBeansOfType(DiscountStrategy.class);

        //利用stream流的方式遍历,扩充discountStrategies
        discountStrategyMap.forEach((key,value)-> discountStrategies.put(value.mark(),value));
    }
}

这里策略工厂类实现了InitializingBean接口,是利用了Spring生命周期中的AfterPropertiesSet方法,也就是在Bean初始化后这一个阶段。首先注入ApplicationContext实例,然后利用它调用GetBeanOfType得到(类名,对应实例)这一个Map对象 ,再利用Stream流进行处理得到了一个Key是mark,value是对应折扣实例的一个map,后续我们就可以使用这个map进行策略模式的使用

4.具体使用

折扣成功,这样业务中就可以利用类似的方式处理优惠券,是不是比if_else更加优雅,同时,后期遇到增删改的情况,是不是就符合了开闭原则

总结

入门了策略模式,我们最后看看他的一些优势:

  • 封装性:策略模式通过将算法封装在独立的类中,使得算法的变化不会影响到使用算法的客户端。
  • 可替换性:可以在运行时选择不同的算法来执行,而不需要修改客户端的代码。
  • 可扩展性:新增算法时,只需新增一个具体的策略类即可,符合开闭原则。
相关推荐
程序员沉梦听雨1 小时前
设计模式之单例模式
单例模式·设计模式
千千寰宇16 小时前
[设计模式/Java/多线程] 设计模式之单例模式【9】
设计模式·操作系统-进程/线程/并发
此木|西贝1 天前
【设计模式】原型模式
java·设计模式·原型模式
振鹏Dong1 天前
策略模式——本质是通过Context类来作为中心控制单元,对不同的策略进行调度分配。
java·策略模式
高 朗1 天前
2025高频面试设计模型总结篇
设计模式·面试·职场和发展
Summer_Xu2 天前
模拟 Koa 中间件机制与洋葱模型
前端·设计模式·node.js
资源大全免费分享2 天前
MacOS 的 AI Agent 新星,本地沙盒驱动,解锁 macOS 操作新体验!
人工智能·macos·策略模式
云徒川2 天前
【设计模式】原型模式
java·设计模式·原型模式
huang_xiaoen2 天前
java设计模式之桥接模式(重生之我在地府当孟婆)
设计模式·桥接模式
HappyGame022 天前
设计模式-观察者模式
观察者模式·设计模式