• Java设计模式——策略模式


    在软件系统可能需要根据不同的情境或条件使用不同的算法或行为,但是这些算法的选择和使用可能会频繁变化。在一个类中或许可以通过一系列的条件判断去区分算法的使用,但是这就会导致代码的臃肿不堪,难以维护和扩展。这时我们需要一种方式来灵活地选择和切换不同的算法。这时就可以考虑策略模式,它的主要优点是实现了算法的解耦,使得算法可以独立于客户端而变化。它提高了代码的可维护性和扩展性,因为新的策略可以很容易地添加到系统中。然而策略模式也可能导致类的数量增加,因为每个算法都需要一个对应的策略类。所以要根据类的数量与灵活性来选择是否使用策略模式。

    一、接口方式实现

    假定一个促销活动方案例子

    1. /**
    2. * 抽象促销策略
    3. */
    4. public interface IPromotionStrategy {
    5. void doPromotion();
    6. }
    7. /**
    8. * 团购优惠策略
    9. */
    10. public class GroupBuyStrategy implements IPromotionStrategy {
    11. @Override
    12. public void doPromotion() {
    13. System.out.println("团购优惠");
    14. }
    15. }
    16. /**
    17. * 返现促销策略
    18. */
    19. public class CashbackStrategy implements IPromotionStrategy {
    20. @Override
    21. public void doPromotion() {
    22. System.out.println("返现促销");
    23. }
    24. }
    25. /**
    26. * 优惠卷抵扣策略
    27. */
    28. public class CouponsStrategy implements IPromotionStrategy {
    29. @Override
    30. public void doPromotion() {
    31. System.out.println("优惠卷抵扣");
    32. }
    33. }
    34. /**
    35. * 无优惠策略
    36. */
    37. public class EmptyStrategy implements IPromotionStrategy {
    38. @Override
    39. public void doPromotion() {
    40. System.out.println("无优惠");
    41. }
    42. }
    43. /**
    44. * 促销活动方案
    45. */
    46. public class PromotionActivity {
    47. private IPromotionStrategy promotionStrategy;
    48. public PromotionActivity(IPromotionStrategy promotionStrategy) {
    49. this.promotionStrategy = promotionStrategy;
    50. }
    51. public void execute() {
    52. promotionStrategy.doPromotion();
    53. }
    54. }

     可结合工厂模式来管理策略

    1. /**
    2. * 促销策略工厂
    3. */
    4. public class PromotionStrategyFactory {
    5. private static final Map strategyMap = new HashMap<>();
    6. private static final IPromotionStrategy EMPTY = new EmptyStrategy();
    7. private PromotionStrategyFactory() {
    8. }
    9. static {
    10. strategyMap.put("COUPONS", new CouponsStrategy());
    11. strategyMap.put("CASHBACK", new CashbackStrategy());
    12. strategyMap.put("GROUPBUY", new GroupBuyStrategy());
    13. }
    14. public static IPromotionStrategy getPromotionStrategy(String key) {
    15. return strategyMap.get(key) == null ? EMPTY : strategyMap.get(key);
    16. }
    17. public static Set getPromotionStrategyKeys() {
    18. return strategyMap.keySet();
    19. }
    20. }

     编写测试用例

    1. /**
    2. * 策略模式-促销活动方案测试
    3. */
    4. @Test
    5. public void testPromotionActivity() {
    6. PromotionActivity activity = new PromotionActivity(new CouponsStrategy());
    7. PromotionActivity activity1 = new PromotionActivity(new CashbackStrategy());
    8. activity.execute();
    9. activity1.execute();
    10. }
    11. /**
    12. * 策略模式-促销活动方案(增强版)测试
    13. */
    14. @Test
    15. public void testPromotionActivityUp() {
    16. Set strategyKeys = PromotionStrategyFactory.getPromotionStrategyKeys();
    17. IPromotionStrategy strategy = PromotionStrategyFactory.getPromotionStrategy("COUPONS");
    18. strategy.doPromotion();
    19. }

    二、抽象类方式实现

    假定一个支付方式选择例子

    1. /**
    2. * 抽象支付类
    3. */
    4. public abstract class Payment {
    5. public abstract String getName();
    6. public ResultMsg pay(String uid, double amount) {
    7. if (queryBalance(uid) < amount) {
    8. return new ResultMsg(500, "支付失败", "余额不足");
    9. }
    10. return new ResultMsg(200, "支付成功", "支付金额:" + amount);
    11. }
    12. protected abstract double queryBalance(String uid);
    13. }
    14. /**
    15. * 订单类
    16. */
    17. @AllArgsConstructor
    18. public class Order {
    19. private String uid;
    20. private String orderId;
    21. private double amount;
    22. public ResultMsg pay() {
    23. return pay(PayStrategy.DEFAULT_PAY);
    24. }
    25. public ResultMsg pay(String key) {
    26. Payment payment = PayStrategy.get(key);
    27. System.out.println("欢迎使用" + payment.getName() + "支付");
    28. System.out.println("本次交易金额为" + amount + "元,开始交易扣款");
    29. return payment.pay(uid, amount);
    30. }
    31. }
    32. /**
    33. * 支付宝
    34. */
    35. public class AliPay extends Payment {
    36. @Override
    37. public String getName() {
    38. return "支付宝";
    39. }
    40. @Override
    41. protected double queryBalance(String uid) {
    42. return 500;
    43. }
    44. }
    45. /**
    46. * 银联支付
    47. */
    48. public class UnionPay extends Payment {
    49. @Override
    50. public String getName() {
    51. return "银联";
    52. }
    53. @Override
    54. protected double queryBalance(String uid) {
    55. return 300;
    56. }
    57. }
    58. /**
    59. * 微信支付
    60. */
    61. public class WechatPay extends Payment {
    62. @Override
    63. public String getName() {
    64. return "微信支付";
    65. }
    66. @Override
    67. protected double queryBalance(String uid) {
    68. return 250;
    69. }
    70. }
    71. /**
    72. * 支付策略
    73. */
    74. public class PayStrategy {
    75. public static final String ALI_PAY = "AliPay";
    76. public static final String WECHAT_PAY = "WechatPay";
    77. public static final String UNION_PAY = "UnionPay";
    78. public static final String DEFAULT_PAY = "AliPay";
    79. private static final Map paymentMap = new HashMap<>();
    80. static {
    81. paymentMap.put(ALI_PAY, new AliPay());
    82. paymentMap.put(WECHAT_PAY, new WechatPay());
    83. paymentMap.put(UNION_PAY, new UnionPay());
    84. paymentMap.put(DEFAULT_PAY, new AliPay());
    85. }
    86. public static Payment get(String key) {
    87. if (!paymentMap.containsKey(key)) {
    88. return paymentMap.get(DEFAULT_PAY);
    89. }
    90. return paymentMap.get(key);
    91. }
    92. }

    编写测试用例

    1. /**
    2. * 策略模式-支付选择
    3. */
    4. @Test
    5. public void testPayChoose() {
    6. Order order = new Order("123", "20220719PAY01", 1000);
    7. ResultMsg pay = order.pay(PayStrategy.ALI_PAY);
    8. System.out.println(pay);
    9. }

  • 相关阅读:
    基于STM32设计的智慧路灯(太阳能+华为云IOT)
    使用GDIView工具排查GDI对象泄漏问题(常用分析工具)
    gcc编译webrtc x64
    android脱壳:一种使用native进行抽取壳脱壳的方法,native版本的frida-fart
    前端实现SuperMap iServer服务增(发布)删改查和刷新的方法.md
    Django里多app
    自然人如何在浙江法院网上完成诉讼——具体流程
    JAVA 中如何实现代码优化(技巧讲解)
    去注释和宏替换——深入理解预处理
    土壤氮磷钾传感器
  • 原文地址:https://blog.csdn.net/LittleMangoYX/article/details/136199129