在数据接收和发送场景打算使用了 if else 进行判断:
-
- if("A".equals(system)){
- ASystem.sync("向A同步数据");
- }
- if("B".equals(system)){
- BSystem.sync("向B同步数据");
- }
- ...
非常麻烦,需求多了很臃肿!
策略模式(Strategy Pattern)定义了一组同类型的算法,在不同的类中封装起来,每种算法可以根据当前场景相互替换,从而使算法的变化独立于使用它们的客户端(即算法的调用者)。
看定义有些抽象,下面的结构图应该会容易理解一些:
- public interface DataProcessingStrategy {
- void receiveData();
- void sendData();
- }
ASystem:
- public class ASystemDataProcessingStrategy implements DataProcessingStrategy {
- @Override
- public void receiveData() {
- // 接收数据的具体实现
- }
-
- @Override
- public void sendData() {
- // 发送数据的具体实现
- }
- }
BSystem:
- public class BSystemDataProcessingStrategy implements DataProcessingStrategy {
- @Override
- public void receiveData() {
- // 接收数据的具体实现
- }
-
- @Override
- public void sendData() {
- // 发送数据的具体实现
- }
- }
- public class Context {
- private DataProcessingStrategy strategy;
-
- public Context(DataProcessingStrategy strategy) {
- this.strategy = strategy;
- }
-
- public void setStrategy(DataProcessingStrategy strategy) {
- this.strategy = strategy;
- }
-
- public void sendData(String data) {
- strategy.sendData(data);
- }
-
- public String receiveData() {
- return strategy.receiveData();
- }
- }
- public class Main {
- public static void main(String[] args) {
- // 创建两个策略对象
- DataProcessingStrategy strategyA = new ASystemDataProcessingStrategy();
- DataProcessingStrategy strategyB = new BSystemDataProcessingStrategy();
-
- // 创建上下文对象,并传入策略对象
- Context context = new Context(strategyA);
- //使用 ASystemDataProcessingStrategy 请求和接收数据
- context.sendData("");
- context.receiveData("");
-
- // 使用 BSystemDataProcessingStrategy 请求和接收数据
- context = new Context(strategyB);
- context.sendData("");
- context.receiveData("");
- }
- }
那么策略模式存在什么样的问题呢?
硬编码的依赖关系:在上述代码中,我们直接将具体的策略类(例如StrategyA和StrategyB)硬编码到上下文类(Context)中。这意味着如果我们想要添加或修改策略,我们需要在上下文类中修改代码。这种硬编码的方式使得系统难以扩展和维护。
客户端与策略的具体实现紧密耦合:由于上下文类Context直接依赖于具体的策略类,因此客户端代码必须了解每个具体策略的细节。这增加了客户端代码的复杂性,并使得客户端代码与策略的具体实现紧密耦合,增加了代码的维护难度。
我们可以使用工厂模式来改进我们的设计。工厂模式可以帮助我们将对象的创建和使用过程分离,使得上下文类和客户端代码不需要了解具体策略的细节,那么我们来修改一下我们的实现:
context可以去除
- // 策略接口和具体的策略类保持不变
- public interface DataProcessingStrategy {
- void sendData(String data);
- String receiveData();
- }
-
- public class ASystemDataProcessingStrategy implements DataProcessingStrategy {
- @Override
- public void sendData(String data) {
- // 发送数据到系统A的实现
- }
-
- @Override
- public String receiveData() {
- // 从系统A接收数据的实现
- }
- }
-
- public class BSystemDataProcessingStrategy implements DataProcessingStrategy {
- @Override
- public void sendData(String data) {
- // 发送数据到系统B的实现
- }
-
- @Override
- public String receiveData() {
- // 从系统B接收数据的实现
- }
- }
-
- public class DataProcessingStrategyFactory {
-
- private static ConcurrentHashMap
strategies = new ConcurrentHashMap<>(); -
- /**
- * 注册策略
- * @param strategyName
- * @param strategy
- */
- public static void register(String strategyName, DataProcessingStrategy strategy) {
- strategies.put(strategyName, strategy);
- }
-
- public static DataProcessingStrategy getStrategy(String strategyName) {
- return strategies.get(strategyName);
- }
-
- }
-
- //client类相关修改
- public class Main {
- public static void main(String[] args) {
- DataProcessingStrategy systemA = DeployStrategyFactory.getStrategy("A");
- //使用 ASystemDataProcessingStrategy 请求和接收数据
- systemA.sendData("");
- systemA.receiveData("");
-
- DataProcessingStrategy systemB = DeployStrategyFactory.getStrategy("B");
- // 使用 BSystemDataProcessingStrategy 请求和接收数据
- systemB.sendData("");
- systemB.receiveData("");
- }
- }
在本篇文章中,我们介绍了策略模式,并在数据接收和发送场景中使用了策略模式。通过使用策略模式,我们可以在客户端代码中根据运行时条件动态地选择一个具体的策略类,并通过这个策略类来改变对象的行为。这样,我们就可以实现不同的数据接收和发送方式,而不需要在客户端代码中进行大量的if-else判断。同时通过策略模式+工厂模式的方式解决了客户端代码与策略的具体实现紧密耦合的问题。当然结合实际的场景灵活运用相应的设计模式也非常重要,避免过度设计。