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

前言

最近接触了优惠券相关的业务,如果是以前,我第一时间想到的就是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 小时前
常用设计模式
java·单例模式·设计模式
lxyzcm19 小时前
深入理解C++23的Deducing this特性(上):基础概念与语法详解
开发语言·c++·spring boot·设计模式·c++23
越甲八千19 小时前
重温设计模式--单例模式
单例模式·设计模式
Vincent(朱志强)19 小时前
设计模式详解(十二):单例模式——Singleton
android·单例模式·设计模式
诸葛悠闲21 小时前
设计模式——桥接模式
设计模式·桥接模式
捕鲸叉1 天前
C++软件设计模式之外观(Facade)模式
c++·设计模式·外观模式
小小小妮子~1 天前
框架专题:设计模式
设计模式·框架
先睡1 天前
MySQL的架构设计和设计模式
数据库·mysql·设计模式
waicsdn_haha1 天前
Postman最新详细安装及使用教程【附安装包】
测试工具·api·压力测试·postman·策略模式·get·delete
Damon_X1 天前
桥接模式(Bridge Pattern)
设计模式·桥接模式