在编程的世界里,每一次按键都是在与代码做策略游戏。我们试图在效率、灵活性和可维护性之间找到平衡点。今天,我们要探讨的是Java中的策略模式,这个模式就像是一个老练的军师,让我们在面对不断变化的需求时能够灵活调整战略。在本文中,我们不仅要学习策略模式的理论,更要通过实战将这个强大的工具纳入我们的编程武库。准备好了吗?让我们开始这场精彩的策略之旅吧
策略模式(Strategy Pattern)是一种设计模式,它使得一个类的行为或其算法可以在运行时更改。这种类型的设计模式属于行为型模式。
在策略模式中,我们创建表示各种策略的对象和一个行为随着策略对象改变而改变的 context 对象。策略对象改变 context 对象的执行算法。
策略(Strategy):一个策略代表了一个算法,或者说是一个行为。在策略模式中,我们可以定义一系列算法或行为,并将每一个算法封装到具有共同接口的独立的类中。
上下文(Context):上下文是使用策略的对象。通常,它会持有一个指向策略对象的引用,并可通过该引用调用策略对象实现的算法。上下文可能会定义一个接口来让策略对象访问它的数据。
策略接口(Strategy Interface):这是一个定义每个策略或算法必须遵守的接口。它是一个共同的接口,让上下文能够在不同策略之间切换而不影响客户端。
具体策略(Concrete Strategies):实现策略接口的类,提供具体的算法或行为。
Strategy(策略接口):定义所有支持的算法的公共接口。Context 使用这个接口来调用 ConcreteStrategy 定义的算法。
ConcreteStrategy(具体策略):实现 Strategy 接口的具体类。每一个 ConcreteStrategy 提供了一个算法或行为。
Context(上下文):持有一个对 Strategy 对象的引用。它可以定义一个接口来让 Strategy 访问它的数据。
// 策略接口
public interface Strategy {
public void execute();
}
// 具体策略A
public class ConcreteStrategyA implements Strategy {
public void execute() {
System.out.println("执行策略A");
}
}
// 具体策略B
public class ConcreteStrategyB implements Strategy {
public void execute() {
System.out.println("执行策略B");
}
}
// 上下文
public class Context {
private Strategy strategy;
// 构造方法,传入策略对象
public Context(Strategy strategy) {
this.strategy = strategy;
}
// 上下文接口
public void executeStrategy() {
strategy.execute();
}
}
// 客户端代码
public class StrategyPatternDemo {
public static void main(String[] args) {
Context context = new Context(new ConcreteStrategyA()); // 使用策略A
context.executeStrategy(); // 输出:执行策略A
context = new Context(new ConcreteStrategyB()); // 使用策略B
context.executeStrategy(); // 输出:执行策略B
}
}
策略模式是一种常用的设计模式,它提供了一系列显著的优点,特别是在处理算法、行为或策略需要在运行时可更换的场景中。以下是策略模式的一些主要优点:
现在我有一个业务它需要根据某一个判断条件(类型)来选择调用某一bean中的相关方法,传统的实现方式如下图

对于上面的方式,会存在这样一个问题,每当我新加一个类型,就要新加一个service实现。并且我的业务中要新加判断,如果我这个业务中存在一个方法会新加一个,如果是100个可能就会新加100个。这样不仅违法了开闭原则,而且还有冗余代码且改起来费时间,最终演变为策略模式,如下图

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
/**
* @author xiaobo
*/
public interface IDataStrategy {
/**
* description: 判断是否有值
*
* @param mainType 主要类型
* @return boolean
* @date 2024/4/19 15:57
*/
boolean supports(String mainType);
}
package com.jxth.dasmart.bridge.configs;
import com.jxth.dasmart.bridge.modules.mid.IMidDataStrategy;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* description: 策略管理
*
* @author bo
* @version 1.0
* @date 2024/4/19 16:10
*/
@Component
@RequiredArgsConstructor
public class DataServiceManager {
private final List<IMidDataStrategy> services;
public IMidDataStrategy getService(String mainType) {
return services.stream()
.filter(service -> service.supports(mainType))
.findFirst()
.orElseThrow(() -> new IllegalArgumentException("No suitable service found for mainType: " + mainType));
}
}
public class BusinessTest {
@Resource
protected DataServiceManager serviceManager;
public void test(String type){
IDataStrategy service = serviceManager.getService(type);
// 实现相关方法
}
}