当前位置: 首页 > news >正文

设计模式-策略模式-200

优点:用来消除 if-else、switch 等多重判断的代码,消除 if-else、switch 多重判断 可以有效应对代码的复杂性。
缺点:会增加类的数量,有的时候没必要为了消除几个if-else而增加很多类,尤其是那些类型又长又臭的
原始代码:

class Example {public static void main(String[] args) {discount("1",20D);}public static Double discount(String type, Double price) {// 策略模式if (Objects.equals(type, "1")) {return price * 0.95;}else if (Objects.equals(type, "2")){return price * 0.9;}return price;}
}

存在2个弊端:
1.if-else过多
2.不符合开闭原则。
开闭原则是对于扩展是开放的,但是对于修改是封闭的,这意味着一个实体是允许在不改变它的源代码的前提下变更它的行为。
策略模式优化大概是三个步骤:

  1. 定义抽象策略接口,因为业务使用接口而不是具体的实现类的话,便可以灵活的替换不同的策略;
  2. 定义具体策略实现类,实现自抽象策略接口,其内部封装具体的业务实现;
  3. 定义策略工厂,封装创建策略实现(算法),对客户端屏蔽具体的创建细节
    优化方法1:

interface DiscountStrategy {Double discount(Double price);
}
class DiscountStrategy1 implements DiscountStrategy{@Overridepublic Double discount(Double price) {return price * 0.95;}
}
class DiscountStrategy2 implements DiscountStrategy{@Overridepublic Double discount(Double price) {return price * 0.9;}
}
class DiscountStrategyFactory {private static final Map<String, DiscountStrategy> STRATEGY_MAP = new HashMap<>();static {STRATEGY_MAP.put("1", new DiscountStrategy1());STRATEGY_MAP.put("2", new DiscountStrategy2());}public static DiscountStrategy chooseStrategy(String type) {return STRATEGY_MAP.get(type);}public static void main(String[] args) {DiscountStrategy discountStrategy = chooseStrategy("1");System.out.println("Discount Price = "+discountStrategy.discount(10D));}
}

运行结果:
在这里插入图片描述
如果新增一个优惠策略,只需要新增一个策略算法实现类即可。但是,添加一个策略算法实现,意味着需要改动策略工厂中的代码,还是不符合开闭原则

如何完整实现符合开闭原则的策略模式,需要借助 Spring 的帮助,详细案例请继续往下看。

@Component
interface DiscountStrategy {Double discount(Double price);String mark();
}
@Component
class DiscountStrategy1 implements DiscountStrategy{@Overridepublic Double discount(Double price) {return price * 0.95;}@Overridepublic String mark() {return "1";}
}
class DiscountStrategy2 implements DiscountStrategy{@Overridepublic Double discount(Double price) {return price * 0.9;}@Overridepublic String mark() {return "2";}
}
@Component
class DiscountStrategyFactory implements InitializingBean {@Autowiredprivate ApplicationContext applicationContext;private static final Map<String, DiscountStrategy> STRATEGY_MAP = new HashMap<>();public  DiscountStrategy chooseStrategy(String type) {return STRATEGY_MAP.get(type);}@Overridepublic void afterPropertiesSet() throws Exception {Map<String, DiscountStrategy> beansOfType = applicationContext.getBeansOfType(DiscountStrategy.class);//        v.mark()为策略对应的key,value为策略对象beansOfType.forEach((k, v) -> STRATEGY_MAP.put(v.mark(), v));}}
@SpringBootTest
class Main {@Autowired DiscountStrategyFactory discountStrategyFactory;@Testvoid contextLoads() {DiscountStrategy discountStrategy = discountStrategyFactory.chooseStrategy("1");System.out.println("Discount Price = "+ discountStrategy.discount(10D));}
}

通过 InitializingBean 接口实现中调用 IOC 容器查找对应策略实现,随后将策略实现 mark() 方法返回值作为 key, 策略实现本身作为 value 添加到 Map 容器中等待客户端的调用。
这里使用的 SpringBoot 测试类,注入策略工厂 Bean,通过策略工厂选择出具体的策略算法类,继而通过算法获取到优惠后的价格。小插曲:如果不想把策略工厂注入 Spring 也可以,实现方法有很多。

总结下本小节,我们通过和 Spring 结合的方式,通过策略设计模式对文初的代码块进行了两块优化:应对代码的复杂性,让其满足开闭原则。更具体一些呢就是 通过抽象策略算法类减少代码的复杂性,继而通过 Spring 的一些特性同时满足了开闭原则,现在来了新需求只要添加新的策略类即可,健壮易扩展。

策略模式的本质依然是对代码设计解耦合,通过三类角色贯穿整个策略模式:抽象策略接口策略工厂以及具体的策略实现类。通过细粒度的策略实现类避免了主体代码量过多,减少了设计中的复杂性

出现 if-else 的代码,一定要使用策略模式优化么?
如果 if-else 判断分支不多并且是固定的,后续不会出现新的分支,那我们完全 可以通过抽函数的方式降低程序复杂性;不要想法设法去除 if-else 语句,存在即合理。而且,使用策略模式会导致类增多,没有必要为了少量的判断分支引入策略模式。


http://www.mrgr.cn/news/38173.html

相关文章:

  • 华为 HCIP-Datacom H12-821 题库 (29)
  • VS Code 配置 Anaconda Python 环境
  • 【洛谷】AT_abc178_e [ABC178E] Dist Max 的题解
  • Vue和axios零基础学习
  • 使用ESPnet的 setup_anaconda.sh安装脚本一步到位,配置conda虚拟环境
  • 言语理解(2)
  • 【反素数】
  • 2024年云南省职业院校技能大赛-云计算应用
  • 一些硬件知识(二十五)
  • 这种膜为啥能随温度变透明?怎么制备的?有啥特点?
  • Synchronized和 ReentrantLock有什么区别?
  • 音视频入门基础:FLV专题(7)——Tag header简介
  • 云原生之容器编排实践-OpenEuler23.09离线安装Kubernetes与KubeSphere
  • 0基础学前端 day6 -- 搭建github pages静态网址
  • Docker官网新手入门教程:从零开始玩转容器
  • 在 commit 里使用 emoji~
  • Java 常用的一些Collection的实现类
  • ai生产力 输出内容变现新方式 AI头像生成教程和变现方式分析
  • 2024新版IDEA创建JSP项目
  • 【Linux】信号