strategy模式

场景 (1)我们可以根据不同的参数来选择一种我们想要执行的优惠计价方式

1.常规

  1. package com.example.demo.pattern.strategy;
  2. /**
  3. * @author chenchao
  4. * @date 2021/11/9
  5. */
  6. public class WithoutStrategyPatternDemo {
  7. public static void main(String[] args) {
  8. // 有一个参数,是discountStyle
  9. // 如果这个参数1,那么选择一种优惠计价的方式
  10. // 如果这个参数2,那么选择一种优惠计价的方式
  11. // 如果这个参数3,那么选择一种优惠计价的方式
  12. int discountStyle = 1;
  13. if(discountStyle == 1) {
  14. System.out.println("执行优惠计价方式1的复杂业务逻辑");
  15. } else if(discountStyle == 2) {
  16. System.out.println("执行优惠计价方式2的复杂业务逻辑");
  17. } else if(discountStyle == 3) {
  18. System.out.println("执行优惠计价方式3的复杂业务逻辑");
  19. } else {
  20. System.out.println("执行默认的优惠计价方式的复杂业务逻辑");
  21. }
  22. // 实际上在我们的业务代码,if else,看起来绝对不是这么短的,也不是这么简单
  23. // 在实际的业务代码中,常见的结构是上面这样的,但是每个if和if else之间的代码行数,可能多达几十行,甚至几百行
  24. // if和else if的判断条件,很模糊,经常就是用一堆变量的比较来判断,是走哪个分支
  25. // 类似上面这样的代码,会让我们在代码写好以后,1年之后,回过头来看这个代码,哇塞,看到了一坨屎一样
  26. // 看都看不懂了:代码太多了,if else if之后的条件判断,我们都看不懂,不知道在判断,if else if里面的代码,量太大了
  27. // 定位个bug,疯了,或者是对这段代码的业务逻辑做一些改动,疯了
  28. // 基本上,你得花个一两天的时间,把这段代码重新读一遍,然后看懂,才能下手写代码
  29. }
  30. }

2.策略模式

  1. package com.example.demo.pattern.strategy;
  2. /**
  3. * @author chenchao
  4. * @date 2021/11/9
  5. */
  6. public class StrategryPatternDemo {
  7. public static void main(String[] args) {
  8. int discountStyle = 1;
  9. DiscountCalculateStrategy strategy = DiscountCalculateStrategryFactory
  10. .getDiscountCalculateStrategy(discountStyle);
  11. Context context = new Context();
  12. context.setStrategy(strategy);
  13. context.calculate();
  14. // 要点1:必须将if else的代码,封装到不同的策略类中
  15. // 要点2:将选择哪种策略的逻辑给放到一个工厂类中去,选择策略的代码务必很简洁
  16. // 要点3:context可有可无,具体是看你的策略执行这块如果就一行代码调用,不需要context
  17. // 如果context中的策略执行逻辑较为复杂一点,context来封装策略类的执行逻辑
  18. }
  19. public interface DiscountCalculateStrategy {
  20. void calculate();
  21. }
  22. public static class DiscountCalculateStrategyA implements DiscountCalculateStrategy {
  23. @Override
  24. public void calculate() {
  25. System.out.println("执行优惠计价方式1的复杂业务逻辑");
  26. }
  27. }
  28. public static class DiscountCalculateStrategyB implements DiscountCalculateStrategy {
  29. @Override
  30. public void calculate() {
  31. System.out.println("执行优惠计价方式2的复杂业务逻辑");
  32. }
  33. }
  34. public static class DiscountCalculateStrategyC implements DiscountCalculateStrategy {
  35. @Override
  36. public void calculate() {
  37. System.out.println("执行优惠计价方式3的复杂业务逻辑");
  38. }
  39. }
  40. public static class DiscountCalculateStrategyDefault implements DiscountCalculateStrategy {
  41. @Override
  42. public void calculate() {
  43. System.out.println("执行默认的优惠计价方式的复杂业务逻辑");
  44. }
  45. }
  46. public static class DiscountCalculateStrategryFactory {
  47. public static DiscountCalculateStrategy getDiscountCalculateStrategy(int discountStyle) {
  48. if(discountStyle == 1) {
  49. return new DiscountCalculateStrategyA();
  50. } else if(discountStyle == 2) {
  51. return new DiscountCalculateStrategyB();
  52. } else if(discountStyle == 3) {
  53. return new DiscountCalculateStrategyC();
  54. } else {
  55. return new DiscountCalculateStrategyDefault();
  56. }
  57. }
  58. }
  59. public static class Context {
  60. private DiscountCalculateStrategy strategy;
  61. public DiscountCalculateStrategy getStrategy() {
  62. return strategy;
  63. }
  64. public void setStrategy(DiscountCalculateStrategy strategy) {
  65. this.strategy = strategy;
  66. }
  67. public void calculate() {
  68. strategy.calculate();
  69. }
  70. }
  71. }

3.说明

策略模式,将会成为最最高频使用的一种设计模式,他的常见应用场景,就是替换掉那一大坨复杂难懂的if else if else。对于那种过于复杂的选择判断逻辑,完全可以将选择哪种策略的过程放到工厂里去。工厂,可以是简单工厂,也可以是工厂方法,也可以是抽象工厂。

策略模式跟命令模式的区别?看起来一样的,但是用处不一样。命令是可以发送出去,然后可以经过一些队列的流转,比如先把命令发送到MQ,接着再处理。策略是说选择了一组策略,立即就要执行的,不会经过其他别的什么处理。而且策略逻辑基本就是用在复杂的if else代码中的

命令模式,可以用在更多别的场景中

思想是不一样的,也许实现上,接口、实现类、工厂来做的,适合的场景是不一样的