状态模式
概念
状态模式(State Pattern)是一种行为设计模式,它允许一个对象在其内部状态改变时改变其行为,使其看起来像改变了自身的类。通过将状态相关的行为抽取到独立的状态类中,状态模式能有效实现状态与行为的分离。
核心组件与职责
组件 | 描述 |
Context | 状态的持有者,维护当前状态对象,并且定义状态切换的方法。 |
State | 抽象状态类,定义状态的通用接口。 |
ConcreteState | 具体状态类,实现具体的状态行为,并在需要时触发状态切换。 |
使用场景
使用场景 | 描述 |
对象行为随状态变化而变化 | 对象的行为依赖于其状态,且运行时状态会发生改变。 |
避免条件语句的状态逻辑 | 使用状态类代替大量的条件分支语句来判断当前状态并执行相应逻辑。 |
状态与行为耦合紧密 | 状态转换与行为逻辑高度相关,不适合用简单的分支或单独类来表示。 |
优点与缺点
优点 | 缺点 |
结构清晰:通过状态类组织代码,消除了条件分支。 | 类数量增加:每个状态都需要独立的类。 |
扩展性强:增加新状态只需添加新的状态类,无需修改原有代码。 | 状态切换复杂:可能需要管理多个状态之间的切换逻辑。 |
状态切换封装:状态变化对客户端透明。 | 引入复杂性:在简单场景下可能过于复杂。 |
与其他模式对比
特性 | 状态模式 | 策略模式 |
核心作用 | 通过状态切换改变对象行为。 | 动态选择算法或行为。 |
实现方式 | 通过状态对象的切换完成不同的逻辑。 | 使用不同策略对象完成不同逻辑。 |
适用场景 | 对象的行为取决于其状态。 | 行为的选择与具体状态无关。 |
实现代码
C++ 实现
#include <iostream>
#include <memory>
// State Interface
class State {
public:
virtual ~State() {}
virtual void handle() = 0;
};
// ConcreteStateA
class ConcreteStateA : public State {
public:
void handle() override {
std::cout << "Handling in State A\n";
}
};
// ConcreteStateB
class ConcreteStateB : public State {
public:
void handle() override {
std::cout << "Handling in State B\n";
}
};
// Context
class Context {
private:
std::unique_ptr<State> state;
public:
void setState(std::unique_ptr<State> newState) {
state = std::move(newState);
}
void request() {
if (state) {
state->handle();
} else {
std::cout << "No state set\n";
}
}
};
// Example
int main() {
Context context;
context.setState(std::make_unique<ConcreteStateA>());
context.request();
context.setState(std::make_unique<ConcreteStateB>());
context.request();
return 0;
}
C# 实现
using System;
// State Interface
public interface IState {
void Handle();
}
// ConcreteStateA
public class ConcreteStateA : IState {
public void Handle() {
Console.WriteLine("Handling in State A");
}
}
// ConcreteStateB
public class ConcreteStateB : IState {
public void Handle() {
Console.WriteLine("Handling in State B");
}
}
// Context
public class Context {
private IState state;
public void SetState(IState newState) {
state = newState;
}
public void Request() {
if (state != null) {
state.Handle();
} else {
Console.WriteLine("No state set");
}
}
}
// Example
public class Program {
public static void Main(string[] args) {
Context context = new Context();
context.SetState(new ConcreteStateA());
context.Request();
context.SetState(new ConcreteStateB());
context.Request();
}
}
类图