定义
策略模式(Strategy Pattern)是一种行为设计模式,它定义了一系列算法,将每个算法封装起来,使它们可以互换。策略模式使得算法可以在不影响客户端的情况下发生变化。此模式让算法独立于使用它的客户而独立变化。
使用场景
策略模式适用于以下几种情况:
- 多个相关类仅在行为上有所不同。策略模式可以将这些行为封装到独立的策略类中,使得它们可以互换。
- 需要使用不同的变体(算法)。例如,对于某些操作需要有不同的实现方式,策略模式可以让这些实现方式独立出来,并且可以方便地进行替换。
- 算法使用客户不应知道的数据。策略模式可以将算法的实现细节隐藏在策略类中。
- 一个类定义了多种行为,并且这些行为在这个类的操作中以多重条件语句的形式出现。策略模式可以将这些行为移到策略类中,使得条件判断语句消失。
主要角色
策略模式包含三个主要角色:
- 策略接口(Strategy Interface):定义了一个算法族,所有的具体策略类都要实现这个接口。
- 具体策略类(Concrete Strategy):实现了策略接口中的具体算法。
- 上下文类(Context):持有一个策略类的引用,并且可以动态地更换策略。
类图
示例代码
以下是策略模式的一个简单实现:
抽象策略角色
// 抽象策略角色
public interface Strategy {
// 策略模式的运算法则
void doSomething();
}
具体策略角色
// 具体策略角色
public class ConcreteStrategy1 implements Strategy {
@Override
public void doSomething() {
System.out.println("具体策略1的运算法则...");
}
}
// 具体策略角色
public class ConcreteStrategy2 implements Strategy {
@Override
public void doSomething() {
System.out.println("具体策略2的运算法则...");
}
}
封装角色
// 封装角色
public class Context {
// 抽象策略
private Strategy strategy;
// 构造函数设置具体策略
public Context(Strategy strategy) {
this.strategy = strategy;
}
// 封装后的策略方法
public void doAnything() {
this.strategy.doSomething();
}
}
客户端代码
public class Client {
public static void main(String[] args) {
// 拿到一个具体的策略
Strategy strategy = new ConcreteStrategy1();
// 创建上下文对象
Context context = new Context(strategy);
// 执行封装后的方法
context.doAnything();
}
}
使用Spring实现策略模式+工厂模式
在实际开发中,使用Spring可以更方便地管理策略模式。我们可以结合工厂模式来动态获取具体的策略类。
定义策略接口
public interface Strategy {
// 策略模式的运算法则
void doSomething();
}
具体策略类
@Component("concreteStrategy1")
public class ConcreteStrategy1 implements Strategy {
@Override
public void doSomething() {
System.out.println("具体策略1的运算法则...");
}
}
```java
@Component("concreteStrategy2")
public class ConcreteStrategy2 implements Strategy {
@Override
public void doSomething() {
System.out.println("具体策略2的运算法则...");
}
}
@Component("defaultStrategy")
public class DefaultStrategy implements Strategy {
@Override
public void doSomething() {
System.out.println("默认策略的运算法则...");
}
}
策略工厂类
@Component
public class StrategyFactory {
// Spring会自动将Strategy接口的实现类注入到这个Map中,key为bean id,value值则为对应的策略实现类
@Autowired
private Map<String, Strategy> strategyMap;
public Strategy getStrategy(String strategyName) {
return strategyMap.get(strategyName);
}
}
测试类
@SpringBootTest
class SpringbootDemoApplicationTests {
@Autowired
private StrategyFactory strategyFactory;
@Test
public void test() {
strategyFactory.getStrategy("concreteStrategy1").doSomething();
strategyFactory.getStrategy("concreteStrategy2").doSomething();
}
}
工作中的实际应用场景
在工作中,策略模式常被用来处理各种需要灵活应对变化的业务逻辑。例如,订阅视频平台的事件处理(异常振动、蒸汽泄露、未带安全帽等)就是一个典型的应用场景。每个类型的事件可以对应一个处理类(策略类),这样在后续如果需要订阅其他事件时,只需增加新的策略类即可,不需要修改原有的代码,符合开闭原则。
具体实现
假设我们需要处理多个视频平台事件,每个事件类型需要一个处理类,我们可以定义如下策略接口和具体策略类:
定义事件处理策略接口
public interface EventHandler {
void handleEvent();
}
具体事件处理策略类
@Component("vibrationEventHandler")
public class VibrationEventHandler implements EventHandler {
@Override
public void handleEvent() {
System.out.println("处理振动事件...");
}
}
@Component("steamLeakEventHandler")
public class SteamLeakEventHandler implements EventHandler {
@Override
public void handleEvent() {
System.out.println("处理蒸汽泄露事件...");
}
}
@Component("noHelmetEventHandler")
public class NoHelmetEventHandler implements EventHandler {
@Override
public void handleEvent() {
System.out.println("处理未带安全帽事件...");
}
}
事件处理策略工厂类
@Component
public class EventHandlerFactory {
@Autowired
private Map<String, EventHandler> eventHandlerMap;
public EventHandler getEventHandler(String eventType) {
return eventHandlerMap.get(eventType);
}
}
客户端代码
@SpringBootTest
class EventHandlingTests {
@Autowired
private EventHandlerFactory eventHandlerFactory;
@Test
public void testEventHandling() {
eventHandlerFactory.getEventHandler("vibrationEventHandler").handleEvent();
eventHandlerFactory.getEventHandler("steamLeakEventHandler").handleEvent();
eventHandlerFactory.getEventHandler("noHelmetEventHandler").handleEvent();
}
}
总结
策略模式是一种非常实用的设计模式,可以有效地应对多变的需求和场景。结合Spring等框架,策略模式的实现变得更加简洁和易于维护。在实际开发中,策略模式可以帮助我们更好地管理算法和业务逻辑,使系统具有更好的扩展性和维护性。
通过本文,我们了解了策略模式的定义、使用场景、主要角色及其实现方式,并结合实际工作中的场景进行了详细讲解,希望能够帮助开发者在实际项目中灵活运用策略模式,提高代码的可维护性和扩展性。