设计模式 20
- 创建型模式(5):工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式
- 结构型模式(7):适配器模式、桥接模式、组合模式、装饰者模式、外观模式、享元模式、代理模式
- 行为型模式(11):责任链模式、命令模式、解释器模式、迭代器模式、中介者模式、备忘录模式、观察者模式、状态模式、策略模式、模板方法模式、访问者模式
文章目录
- [设计模式 20](#设计模式 20)
-
- [状态模式(State Pattern)](#状态模式(State Pattern))
-
- [1 定义](#1 定义)
- [2 结构](#2 结构)
- [3 示例代码](#3 示例代码)
- [6 特点](#6 特点)
- [7 适用场景](#7 适用场景)
- [8 总结](#8 总结)
状态模式(State Pattern)
1 定义
状态模式的核心思想是将与状态相关的行为封装在独立的状态对象中,并通过状态对象来管理对象的状态转换。这样,原始对象在其状态发生变化时,会自动切换到对应的状态对象,从而表现出不同的行为。
2 结构
状态模式包含以下角色:
- 上下文(Context): 维护一个当前状态,并在状态发生变化时,切换到新的状态对象。上下文对象向客户端暴露接口,但行为的实现由状态对象负责。
- 状态接口(State): 定义状态的接口,声明在该状态下对象可以执行的行为。
- 具体状态(ConcreteState): 实现状态接口,定义该状态下的具体行为。当上下文处于此状态时,行为由具体状态对象执行。
UML 类图
scss
+-------------------+ +-----------------------------------+
| Context | | State |
+-------------------+ +-----------------------------------+
| - state: State |<------| + Handle(context: Context): void |
| + Request(): void | +-----------------------------------+
+-------------------+ ^ ^
| |
| |
+-----------------------------------+ +-----------------------------------+
| ConcreteStateA | | ConcreteStateB |
+-----------------------------------+ +-----------------------------------+
| + Handle(context: Context): void | | + Handle(context: Context): void |
+-----------------------------------+ +-----------------------------------+
3 示例代码
假设我们要实现一个简单的电灯开关系统,电灯可以处于"开"和"关"两种状态,并且根据当前的状态来执行不同的操作。
状态接口
csharp
// 状态接口
public interface IState
{
void Handle(Context context);
}
具体状态类
csharp
// 具体状态 - 开灯状态
public class OnState : IState
{
public void Handle(Context context)
{
Console.WriteLine("The light is already ON.");
context.SetState(new OffState());
}
}
// 具体状态 - 关灯状态
public class OffState : IState
{
public void Handle(Context context)
{
Console.WriteLine("The light is OFF. Turning it ON.");
context.SetState(new OnState());
}
}
上下文类
csharp
// 上下文类
public class Context
{
private IState _state;
public Context(IState state)
{
_state = state;
}
public void SetState(IState state)
{
_state = state;
}
public void Request()
{
_state.Handle(this);
}
}
客户端代码
csharp
class Program
{
static void Main(string[] args)
{
Context context = new Context(new OffState());
// 初始状态为关灯状态
context.Request(); // 关灯 -> 开灯
// 再次请求
context.Request(); // 开灯 -> 关灯
// 再次请求
context.Request(); // 关灯 -> 开灯
}
}
运行结果
plaintext
The light is OFF. Turning it ON.
The light is already ON.
The light is OFF. Turning it ON.
在这个例子中,Context
类维护一个当前状态,当调用 Request()
方法时,会根据当前状态执行相应的操作并切换到下一个状态。OnState
和 OffState
是两种具体的状态类,分别定义了在不同状态下的行为。
6 特点
-
优点:
-
减少复杂性: 通过将状态相关的行为封装在独立的状态对象中,状态模式消除了大量的条件分支语句,使代码更加清晰和易于维护。
-
状态转换灵活: 可以很容易地添加、删除或修改状态对象,扩展系统的功能,而无需修改上下文类。
-
符合单一职责原则: 状态模式将与状态相关的行为封装在不同的状态类中,使得每个类只负责一种状态的行为,简化了代码的管理。
-
-
缺点:
-
增加类的数量: 每个状态都需要定义一个具体的状态类,当状态过多时,可能会导致类的数量急剧增加,增加系统的复杂性。
-
状态之间的依赖: 如果状态之间存在复杂的依赖关系,可能会导致状态之间的转换逻辑变得复杂,难以维护。
-
7 适用场景
- 对象的行为依赖于其状态: 当一个对象的行为依赖于其状态,并且它的状态会在运行时改变时,状态模式非常适用。
- 状态逻辑复杂: 当状态转换的逻辑非常复杂,或者状态之间的转换规则经常变化时,状态模式能够有效地管理这些逻辑。
- 消除条件分支: 如果代码中存在大量的条件分支语句来处理不同的状态,状态模式可以通过将状态逻辑分散到不同的状态类中来简化代码。
8 总结
状态模式通过将状态相关的行为封装在独立的状态对象中,简化了对象的状态管理逻辑。它消除了大量的条件分支语句,使代码更加清晰和易于扩展。尽管状态模式可能会增加类的数量,但它为管理复杂的状态转换逻辑提供了一种灵活且有效的解决方案。