设计模式:策略设计模式

一、什么是策略设计模式

1.1 策略设计模式定义

策略设计模式(Strategy Pattern)是一种定义一系列算法的方法,从概念上来看,所有这些算法完成的都是相同的工作,只是实现不同,它可以让算法的变化独立于使用算法的客户端。

1.2 策略设计模式应用场景

策略设计模式通常在以下场景中使用:

  • 当需要在不同情况下使用不同的算法时
  • 当一个类有多种行为或算法,并且这些行为或算法可以在运行时切换时
  • 当需要避免使用多重条件语句或大量的if-else语句时

二、策略设计模式的组成部分

策略设计模式通常由三个部分组成:

2.1 抽象策略类

抽象策略类定义了一个算法族,其中每个算法都是一个方法。抽象策略类通过抽象方法来约束具体策略类的行为。

public interface Strategy {
    public int doOperation(int num1, int num2);
}

2.2 具体策略类

具体策略类实现了抽象策略类中定义的算法,每个具体策略类都实现了一种算法。

public class OperationAdd implements Strategy {
   public int doOperation(int num1, int num2) {
      return num1 + num2;
   }
}

public class OperationSubtract implements Strategy {
   public int doOperation(int num1, int num2) {
      return num1 - num2;
   }
}

public class OperationMultiply implements Strategy {
   public int doOperation(int num1, int num2) {
      return num1 * num2;
   }
}

2.3 环境类

环境类持有一个抽象策略类的引用,用于调用具体的策略类中实现的算法。

public class Context {
   private Strategy strategy;

   public Context(Strategy strategy){
      this.strategy = strategy;
   }

   public int executeStrategy(int num1, int num2){
      return strategy.doOperation(num1, num2);
   }
}

三、策略设计模式的实现步骤

在使用策略设计模式时,通常需要按照以下步骤进行:

3.1 定义策略接口或抽象类

定义一个抽象的策略接口或抽象类,其中声明了一个抽象的算法方法。

public interface Strategy {
   public int doOperation(int num1, int num2);
}

3.2 实现具体策略类

实现具体的策略类,这些类实现了策略接口或抽象类中定义的算法。

public class OperationAdd implements Strategy {
   public int doOperation(int num1, int num2) {
      return num1 + num2;
   }
}

public class OperationSubtract implements Strategy {
   public int doOperation(int num1,int num2) {
      return num1 - num2;
   }
}

public class OperationMultiply implements Strategy {
   public int doOperation(int num1, int num2) {
      return num1 * num2;
   }
}

3.3 定义环境类

定义一个环境类,持有一个抽象策略类的引用,用于调用具体的策略类中实现的算法。

public class Context {
   private Strategy strategy;

   public Context(Strategy strategy){
      this.strategy = strategy;
   }

   public int executeStrategy(int num1, int num2){
      return strategy.doOperation(num1, num2);
   }
}

3.4 在环境类中使用策略类

在环境类中使用具体的策略类。

public static void main(String[] args) {
   Context context = new Context(new OperationAdd());        
   System.out.println("10 + 5 = " + context.executeStrategy(10, 5));

   context = new Context(new OperationSubtract());       
   System.out.println("10 - 5 = " + context.executeStrategy(10, 5));

   context = new Context(new OperationMultiply());        
   System.out.println("10 * 5 = " + context.executeStrategy(10, 5));
}

四、策略设计模式的优缺点

4.1 优点

  • 策略设计模式能够提供更好的扩展性,由于策略类是可以自由切换的,因此可以非常方便地实现新的算法或业务逻辑。
  • 策略设计模式可以提高代码的复用性,由于不同的算法可以共享同一个抽象策略类,因此可以避免重复的代码。
  • 策略设计模式能够提高代码的可读性和可维护性,由于不同的算法都被封装在不同的策略类中,因此代码结构更加清晰,易于理解和维护。

4.2 缺点

  • 策略设计模式需要定义大量的策略类,这会增加代码量和复杂度。
  • 策略设计模式需要客户端了解不同的策略类并选择合适的策略类,这会增加客户端的负担。

五、策略设计模式与其他设计模式的区别

5.1 策略设计模式与模板方法模式的区别

策略设计模式和模板方法模式都是行为型设计模式,它们都关注于类的行为。它们的区别在于:

  • 策略设计模式关注于算法的不同实现,而模板方法模式关注于算法的不同步骤。
  • 在策略设计模式中,不同的算法可以自由切换,而在模板方法模式中,算法的不同步骤是固定的,只能在子类中重写。
  • 策略设计模式中,客户端需要了解不同的策略类并选择合适的策略类,而在模板方法模式中,客户端不需要了解不同的实现方式。

5.2 策略设计模式与状态模式的区别

策略设计模式和状态模式都是行为型设计模式,它们都关注于对象的状态变化。它们的区别在于:

  • 策略设计模式关注于算法的不同实现,而状态模式关注于对象的不同状态。
  • 在策略设计模式中,不同的算法是可以自由切换的,而在状态模式中,对象的不同状态是有限的,且状态之间是有转换关系的。
  • 在策略设计模式中,客户端需要了解不同的策略类并选择合适的策略类,而在状态模式中,客户端不需要了解不同的状态,只需要调用对象的方法即可。

六、策略设计模式的应用实例

6.1 实例说明

假设我们正在开发一个计算器程序,该程序可以根据用户的选择进行加、减、乘、除四种运算。为了实现这个功能,我们可以使用策略设计模式,将每种运算封装在不同的策略类中。

6.2 代码实现

在我们将通过代码实现上述的计算器程序,首先我们需要定义一个策略接口,用于声明算法方法:

public interface Strategy {
   public int doOperation(int num1, int num2);
}

接着,我们需要实现具体的策略类,这些类分别对应加、减、乘、除四种运算:

public class OperationAdd implements Strategy {
   public int doOperation(int num1, int num2) {
      return num1 + num2;
   }
}

public class OperationSubtract implements Strategy {
   public int doOperation(int num1, int num2) {
      return num1 - num2;
   }
}

public class OperationMultiply implements Strategy {
   public int doOperation(int num1, int num2) {
      return num1 * num2;
   }
}

public class OperationDivide implements Strategy {
   public int doOperation(int num1, int num2) {
      return num1 / num2;
   }
}

接下来,我们需要定义一个环境类,用于持有具体的策略类,并调用其方法:

public class Context {
   private Strategy strategy;

   public Context(Strategy strategy){
      this.strategy = strategy;
   }

   public int executeStrategy(int num1, intnum2){
      return strategy.doOperation(num1, num2);
   }
}

最后,我们可以在客户端代码中使用上述的类来完成计算器的功能:

public static void main(String[] args) {
   Context context = new Context(new OperationAdd());        
   System.out.println("10 + 5 = " + context.executeStrategy(10, 5));

   context = new Context(new OperationSubtract());       
   System.out.println("10 - 5 = " + context.executeStrategy(10, 5));

   context = new Context(new OperationMultiply());        
   System.out.println("10 * 5 = " + context.executeStrategy(10, 5));

   context = new Context(new OperationDivide());        
   System.out.println("10 / 5 = " + context.executeStrategy(10, 5));
}

输出结果为:

10 + 5 = 15
10 - 5 = 5
10 * 5 = 50
10 / 5 = 2

通过上述代码,我们可以看到策略设计模式可以非常方便地实现不同算法的切换,并且代码结构更加清晰易懂。

七、扩展点

7.1 策略类的动态切换

在上述的示例代码中,我们需要在客户端代码中手动创建不同的策略类对象,并将其传递给环境类的构造方法。如果我们希望在程序运行过程中动态切换策略类,就需要对代码进行修改。

一种解决方案是使用反射机制,通过类名动态创建策略类对象。具体实现可以参考以下代码:

public class Context {
   private Strategy strategy;

   public Context(String className) {
      try {
         Class<?> clazz = Class.forName(className);
         this.strategy = (Strategy) clazz.newInstance();
      } catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
         e.printStackTrace();
      }
   }

   public int executeStrategy(int num1, intnum2){
      return strategy.doOperation(num1, num2);
   }
}

在上述代码中,我们新增了一个构造方法,该方法接受一个字符串类型的参数,用于指定具体的策略类。在方法内部,我们使用了反射机制来创建策略类对象,并将其赋值给环境类的成员变量。这样,我们就可以在程序运行过程中动态切换策略类了。

7.2 策略类的缓存

在上述的示例代码中,每次创建新的策略类对象都需要消耗一定的时间和内存。如果我们需要多次调用同一个策略类,就会造成资源的浪费。

一种解决方案是使用策略类的缓存,将已经创建的策略类对象缓存起来,避免重复创建。具体实现可以参考以下代码:

public class Context {
   private Map<String, Strategy> strategyMap = new HashMap<>();

   public Context(String className) {
      if (strategyMap.containsKey(className)) {
         this.strategy = strategyMap.get(className);
      } else {
         try {
            Class<?> clazz = Class.forName(className);
            this.strategy = (Strategy) clazz.newInstance();
            strategyMap.put(className, strategy);
         } catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
            e.printStackTrace();
         }
      }
   }

   public int executeStrategy(int num1, intnum2){
      return strategy.doOperation(num1, num2);
   }
}

在上述代码中,我们使用了一个HashMap来缓存已经创建的策略类对象。在创建策略类对象时,首先检查缓存中是否已经存在该类对象,如果存在则直接返回,否则才创建新的对象,并将其添加到缓存中。这样,我们就可以避免重复创建策略类对象,提高了程序的性能。

八、总结

策略设计模式是一种非常实用的设计模式,它可以让我们在程序运行过程中动态地切换算法,从而提高程序的灵活性和可扩展性。通过策略设计模式,我们可以将算法的实现与客户端代码解耦,从而使代码更加清晰易懂。

在实现策略设计模式时,我们需要定义一个策略接口,用于声明算法方法,然后实现具体的策略类,这些类分别对应不同的算法实现。接着,我们需要定义一个环境类,用于持有具体的策略类,并调用其方法。在客户端代码中,我们可以创建不同的策略类对象,并将其传递给环境类,从而实现不同算法的切换。

扩展方面,我们可以通过策略类的动态切换和缓存等方式,进一步提高程序的灵活性和性能。

总的来说,策略设计模式是一种非常实用的设计模式,可以帮助我们更好地组织代码,提高程序的可维护性和可扩展性。在实际开发中,我们应该根据具体的需求选择合适的策略设计模式,并注意代码的可读性和可维护性。

 

HTML 6992 字节 612 单词 256 行

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
策略模式是一种行为型设计模式,它允许在运行时动态地选择算法的行为,这些算法在同一接口中定义。在策略模式中,创建一个策略接口,然后定义多个实现该接口的具体策略类。接着,在使用策略的时候,需要根据不同的参数选择不同的策略类,然后调用其相应的方法。 在使用策略模式的时候,我们可以将不同的服务(service)接口封装成不同的策略类,在运行时根据参数选择不同的策略类,从而调用不同的服务接口。这可以使得代码更加灵活,易于扩展和维护。 下面是一个使用策略模式实现根据参数调用不同服务接口的示例代码: ```java // 策略接口 interface ServiceStrategy { void doService(); } // 具体策略类1 class Service1 implements ServiceStrategy { @Override public void doService() { System.out.println("调用服务1"); } } // 具体策略类2 class Service2 implements ServiceStrategy { @Override public void doService() { System.out.println("调用服务2"); } } // 上下文类 class ServiceContext { private ServiceStrategy strategy; public void setStrategy(ServiceStrategy strategy) { this.strategy = strategy; } public void executeService() { this.strategy.doService(); } } // 测试代码 public class Main { public static void main(String[] args) { ServiceContext context = new ServiceContext(); // 根据参数选择不同的策略类 String serviceType = "service1"; if (serviceType.equals("service1")) { context.setStrategy(new Service1()); } else if (serviceType.equals("service2")) { context.setStrategy(new Service2()); } // 调用服务 context.executeService(); } } ``` 在上面的示例代码中,我们定义了一个策略接口 `ServiceStrategy`,并实现了两个具体的策略类 `Service1` 和 `Service2`,分别对应不同的服务接口。然后,我们定义了一个上下文类 `ServiceContext`,用于执行服务。在上下文类中,我们使用了策略模式,根据参数选择不同的策略类,然后调用其相应的服务接口。最后,在测试代码中,我们演示了如何使用策略模式调用不同的服务接口。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值