设计模式之策略模式

介绍

在软件开发中常常遇见这样的问题:实现某个功能可以有多种算法或者策略,我们根据实际情况选择不同的算法或者策略来完成该功能。例如,排序算法,可以有多种的实现方式。

那么,针对这种情况,应该怎么处理?是将这些算法写在一个类中,每一个方法对应一个具体的排序算法;还是将这些排序算法封装在同一个方法中,通过 if...else 或者 case 等条件判断语句来选择具体的算法。这 2 种实现方法我们都可以称之为硬编码。当然,这样是可以实现需求,但是,当很多算法在一个类时,这个类就会变得很臃肿,维护成本就会变高,并且在维护时容易发生错误,如果我们需要新增或者修改算法类的源码,这个就需要动封装好的类,那么这就违背了单一职责和开闭原则了。

如果将这些算法或者策略抽象出来,提供统一的接口,不同的算法或者策略有不同的实现类,这样在程序客户端就可以通过注入不同的实现对象来实现算法或者策略的动态替换,这种模式的可扩展性,可维护性也就更高,这就是我们今天要学习的策略模式。

定义

策略模式定义了一系列算法,并将每一个算法封装起来,而且使他们还可以相互替换,策略模式让算法独立于使用它的客户而独立变化。

使用场景

  • 针对同一类型问题的多种处理方式,仅仅是具体行为有差别时。
  • 需要安全的封装多种同一类型操作时。
  • 出现同一抽象类有多个子类,而又需要使用 if-else 或者 switch-case 来选择具体子类时。

UML 类图

 

<figcaption></figcaption>](https://free.imgsha.com/i/E9ZAp)

  • Context :用来操作策略的上下文环境
  • Stragety : 策略的抽象
  • ConcreteStragetyA, ConcreteStragetyB 具体策略实现。

简单示例

需求:对交通工具计算车费,一般轿车,中等轿车,豪华轿车。

 

   /*
   * 计算费用接口
   * 
   */
  public interface ICalculateStrategy {

      /**
       * 按距离计算车费
       * @param km  公里数                                                                                                         
       * @return
       */
      int calculatePrice(int km);
  }

各种车的计算方式

 

  //普通车
  public class GeneralCar implements ICalculateStrategy {
      @Override
     public int calculatePrice(int km) {
          if (km > 0 && km <= 5)
              return 5;
          if (km > 5 && km <= 7)
              return 7;
          if (km > 7 && km <= 10)
              return 10;
          return 10;
      }
  }

 

  //中级车
  public class MediumCar implements ICalculateStrategy {
      @Override
      public int calculatePrice(int km) {
          if (km > 0 && km <= 5)
              return 6;
          if (km > 5 && km <= 7)
              return 9;
          if (km > 7 && km <= 10)
              return 12;
          return 12;
      }
  }

 

  //高级车
  public class LuxuryCar implements ICalculateStrategy {
      @Override
      public int calculatePrice(int km) {
          if (km > 0 && km <= 5)
              return 8;
          if (km > 5 && km <= 7)
              return 13;
          if (km > 7 && km <= 10)
              return 15;
          return 13;
      }
  }

我们在创建一个操作 Context 策略的类

 

  public class TransportationCalculator {

      /**
       * 交通工具计算费用策略类
       */
      private ICalculateStrategy iCalculateStrategy = new GeneralCar();

      /**
       * 设置策略
       * @param calculateStrategy
       */
      public void setStrategy(ICalculateStrategy calculateStrategy) {
          this. iCalculateStrategy = calculateStrategy;
      }

      public int calcu(int km){
          return iCalculateStrategy.calculatePrice(km);
      }
  }

测试:

 

  @Test
  public void test8(){
    TransportationCalculator transportationCalculator = new 
  TransportationCalculator();
    System.out.println("普通车 1 km RMB:" + transportationCalculator.calcu(5));

    transportationCalculator.setStrategy(new MediumCar());
    System.out.println("中级车 1 km RMB:" + transportationCalculator.calcu(5));

    transportationCalculator.setStrategy(new LuxuryCar());
    System.out.println("豪华车 1 km RMB:" + transportationCalculator.calcu(5));
      }

Output:

 

  普通车 1 km RMB:5
  中级车 1 km RMB:6
  豪华车 1 km RMB:8

有没有发现这种写法不仅结构变得清晰,而且还易维护,扩展性也很强。

总结

策略模式主要用来分离算法,在相同的行为抽象下有不同的具体实现策略。在这个模式很好地演示了开闭原则,也就是定义接口抽象,注入不同的实现,从而达到很好的可扩展性。

优点:

  • 结构清晰明了、使用简单直观;
  • 耦合度相对而言较低,扩展方便;
  • 操作封装也更为彻底,数据更为安全;

缺点:

  • 随着策略的增加,子类也会变得繁多
资源下载链接为: https://pan.quark.cn/s/f989b9092fc5 今天给大家分享一个关于C#自定义字符串替换方法的实例,希望能对大家有所帮助。具体介绍如下: 之前我遇到了一个算法题,题目要求将一个字符串中的某些片段替换为指定的新字符串片段。例如,对于源字符串“abcdeabcdfbcdefg”,需要将其中的“cde”替换为“12345”,最终得到的结果字符串是“ab12345abcdfb12345fg”,即从“abcdeabcdfbcdefg”变为“ab12345abcdfb12345fg”。 经过分析,我发现不能直接使用C#自带的string.Replace方法来实现这个功能。于是,我决定自定义一个方法来完成这个任务。这个方法的参数包括:原始字符串originalString、需要被替换的字符串片段strToBeReplaced以及用于替换的新字符串片段newString。 在实现过程中,我首先遍历原始字符串,查找需要被替换的字符串片段strToBeReplaced出现的位置。找到后,就将其替换为新字符串片段newString。需要注意的是,在替换过程中,要确保替换操作不会影响后续的查找和替换,避免遗漏或重复替换的情况发生。 以下是实现代码的大概逻辑: 初始化一个空的字符串result,用于存储最终替换后的结果。 使用IndexOf方法在原始字符串中查找strToBeReplaced的位置。 如果找到了,就将originalString中从开头到strToBeReplaced出现位置之前的部分,以及newString拼接到result中,然后将originalString的查找范围更新为strToBeReplaced之后的部分。 如果没有找到,就直接将剩余的originalString拼接到result中。 重复上述步骤,直到originalStr
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值