策略模式、状态机详细解读
策略模式 (Strategy Pattern)
策略模式 (Strategy Pattern) 是一种行为型设计模式,旨在将一组算法封装成独立的类,使得它们可以相互替换。这种模式让算法的变化不会影响到使用算法的客户,减少了类之间的耦合。策略模式通常用于处理一类问题,但具有多种解决方案时的情况。
一、策略模式的结构
策略模式主要包含以下角色:
- Context(上下文):
- 维护对
Strategy
对象的引用。 - 根据实际情况选择和调用特定的策略类。
- 维护对
- Strategy(抽象策略):
- 定义所有策略类的公共接口。通常是一个抽象类或接口,声明一些方法。
- ConcreteStrategy(具体策略):
- 实现
Strategy
接口的具体类,封装了具体的算法。
- 实现
二、策略模式的类图
+---------------+
| Context |
+---------------+
|
| uses
v
+---------------+
| Strategy |
+---------------+
^
|
+--------+---------+
| |
+-----------+ +-------------+
| StrategyA | | StrategyB |
+-----------+ +-------------+
三、策略模式的实现(Java 示例)
假设我们要实现一个支付系统,可以支持 支付宝 (Alipay)、微信支付 (WeChatPay) 和 银联支付 (UnionPay)。
1. 定义策略接口 (Strategy):
interface PaymentStrategy {
void pay(int amount);
}
2. 具体策略实现类 (ConcreteStrategy):
// 支付宝支付策略
class AlipayStrategy implements PaymentStrategy {
public void pay(int amount) {
System.out.println("Using Alipay to pay: " + amount + "元");
}
}
// 微信支付策略
class WeChatPayStrategy implements PaymentStrategy {
public void pay(int amount) {
System.out.println("Using WeChatPay to pay: " + amount + "元");
}
}
// 银联支付策略
class UnionPayStrategy implements PaymentStrategy {
public void pay(int amount) {
System.out.println("Using UnionPay to pay: " + amount + "元");
}
}
3. 定义上下文类 (Context):
class PaymentContext {
private PaymentStrategy strategy;
// 设置支付策略
public void setPaymentStrategy(PaymentStrategy strategy) {
this.strategy = strategy;
}
// 执行支付
public void executePayment(int amount) {
strategy.pay(amount);
}
}
4. 客户端测试代码:
public class StrategyPatternDemo {
public static void main(String[] args) {
PaymentContext context = new PaymentContext();
// 使用支付宝支付
context.setPaymentStrategy(new AlipayStrategy());
context.executePayment(100);
// 使用微信支付
context.setPaymentStrategy(new WeChatPayStrategy());
context.executePayment(200);
// 使用银联支付
context.setPaymentStrategy(new UnionPayStrategy());
context.executePayment(300);
}
}
输出结果:
Using Alipay to pay: 100元
Using WeChatPay to pay: 200元
Using UnionPay to pay: 300元
四、策略模式的优缺点
优点:
- 开闭原则:可以在不修改原有代码的情况下增加新策略。
- 可扩展性强:各个策略类可以独立变化。
- 减少代码冗余:将算法封装成独立的类,有助于复用。
缺点:
- 增加类数量:如果策略过多,会导致类的数量增加,增加系统复杂性。
- 客户端需要知道策略:客户端需要理解不同策略的区别,并选择合适的策略。
应用场景:
- 需要在多种算法之间进行选择时,如不同的排序算法、加密算法等。
- 需要在运行时动态决定某一行为的具体实现时。
- 如 支付系统、日志系统 和 数据处理系统 等。
状态机 (State Machine)
状态机 (State Machine),又称为 有限状态机 (Finite State Machine, FSM),是一种用于表示对象状态及其状态转换的模型。它定义了一组状态以及状态之间的转换规则,通过事件触发状态的转变,从而改变对象的行为。
一、状态机的基本概念
- 状态 (State):系统在任一时刻所处的情况或条件。
- 事件 (Event):触发状态转换的条件或动作。
- 转换 (Transition):从一个状态到另一个状态的变化。
- 动作 (Action):状态转换时执行的操作。
二、状态机的示例
假设我们要实现一个简单的订单管理系统,它包含以下几个状态:
- 创建 (Created):订单刚创建。
- 已支付 (Paid):订单已支付。
- 已发货 (Shipped):订单已发货。
- 已完成 (Completed):订单已完成。
状态转换图如下:
Created → [支付] → Paid → [发货] → Shipped → [完成] → Completed
三、状态机的实现(Java 示例)
1. 定义状态接口:
interface OrderState {
void handleOrder(OrderContext context);
}
2. 具体状态实现类:
// 创建状态
class CreatedState implements OrderState {
public void handleOrder(OrderContext context) {
System.out.println("订单已创建,等待支付...");
context.setState(new PaidState());
}
}
// 已支付状态
class PaidState implements OrderState {
public void handleOrder(OrderContext context) {
System.out.println("订单已支付,等待发货...");
context.setState(new ShippedState());
}
}
// 已发货状态
class ShippedState implements OrderState {
public void handleOrder(OrderContext context) {
System.out.println("订单已发货,等待收货...");
context.setState(new CompletedState());
}
}
// 已完成状态
class CompletedState implements OrderState {
public void handleOrder(OrderContext context) {
System.out.println("订单已完成!");
}
}
3. 定义上下文类 (Context):
class OrderContext {
private OrderState state;
public OrderContext() {
state = new CreatedState(); // 初始状态
}
public void setState(OrderState state) {
this.state = state;
}
public void next() {
state.handleOrder(this);
}
}
4. 客户端测试代码:
public class StateMachineDemo {
public static void main(String[] args) {
OrderContext order = new OrderContext();
order.next(); // 订单已创建,等待支付
order.next(); // 订单已支付,等待发货
order.next(); // 订单已发货,等待收货
order.next(); // 订单已完成
}
}
输出结果:
订单已创建,等待支付...
订单已支付,等待发货...
订单已发货,等待收货...
订单已完成!
四、状态机的优缺点
优点:
- 清晰的状态管理:能够清晰地定义对象在不同状态下的行为。
- 易于维护:将状态与行为封装在一起,代码易于扩展和维护。
- 提高可读性:通过状态和转换将复杂的业务逻辑简化。
缺点:
- 类的增加:如果状态过多,会导致类数量增加,增加系统复杂性。
- 状态切换成本:频繁的状态切换可能会导致性能开销。
应用场景:
- 订单处理系统:如电商平台中的订单状态管理。
- 游戏开发:如角色状态(行走、跳跃、攻击等)的管理。
- 协议解析:如网络协议中的状态管理(TCP 三次握手等)。
- 工作流系统:如审批流程的状态转换。
总结
- 策略模式 适用于有多种算法可供选择的场景,能够在运行时灵活选择算法,提高系统的扩展性。
- 状态机 适合复杂状态管理的场景,能够清晰地定义对象在不同状态下的行为,并有效处理状态之间的转换。
- 两者虽然解决的问题不同,但在实际应用中可以结合使用,以构建更加灵活和健壮的系统。