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

前言

最近接触了优惠券相关的业务,如果是以前,我第一时间想到的就是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 天前
状态模式(State Pattern)
设计模式
李广坤1 天前
观察者模式(Observer Pattern)
设计模式
李广坤1 天前
中介者模式(Mediator Pattern)
设计模式
李广坤1 天前
迭代器模式(Iterator Pattern)
设计模式
李广坤2 天前
解释器模式(Interpreter Pattern)
设计模式
阿无,2 天前
java23种设计模式之前言
设计模式
Asort2 天前
JavaScript设计模式(八):组合模式(Composite)——构建灵活可扩展的树形对象结构
前端·javascript·设计模式
数据智能老司机2 天前
数据工程设计模式——数据基础
大数据·设计模式·架构
笨手笨脚の2 天前
设计模式-代理模式
设计模式·代理模式·aop·动态代理·结构型设计模式
Overboom2 天前
[C++] --- 常用设计模式
开发语言·c++·设计模式