自学内容网 自学内容网

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

前言

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

概念引入

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

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

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

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

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

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

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

        2.优惠券的具体实现类

/*
 * 八折的折扣类,首先要实现之前的折扣接口,然后重写方法
 * 利用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生命周期使用

/*
 * 这里利用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更加优雅,同时,后期遇到增删改的情况,是不是就符合了开闭原则。 

总结 

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

  • 封装性:策略模式通过将算法封装在独立的类中,使得算法的变化不会影响到使用算法的客户端。
  • 可替换性:可以在运行时选择不同的算法来执行,而不需要修改客户端的代码。
  • 可扩展性:新增算法时,只需新增一个具体的策略类即可,符合开闭原则。

原文地址:https://blog.csdn.net/qq_52692506/article/details/140571069

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!