状态模式
前言
状态模式中类的行为是由状态决定的,在不同的状态下有不同的行为,核心是状态与行为绑定,不同的状态有不同的行为。在开发中,对某一项操作,可能存在不同的情况,依据不同的状态,执行对应的操作。比如网购时订单的状态改变。
一、状态模式(State Pattern)
根据不同的状态做出不同的行为。状态驱动行为,行为决定状态,绑定状态和行为。
二、应用场景
- 行为随状态改变而改变的场景
- 操作方法中含有大量的操作分支结构,并且这些分支操作取决于对象的状态。
三、角色
- 环境类角色(Context):定义客户端需要的接口,内部维护一个当前状态实例,负责具体状态的切换
- 抽象状态角色(IState):定义该状态下的行为,可以有一个或多个行为。
- 具体状态角色(ConcreteState):具体实现该状态对应的行为,并且在需要的情况下状态切换。
四、使用步骤
1.抽象状态
代码如下(示例):定义状态处理程序
/// <summary>
/// 抽象状态
/// </summary>
public interface IState
{
void handle();
}
2.抽象状态的具体实现
代码如下(示例):
/// <summary>
/// 具体实现状态
/// </summary>
public class ConcreteStateA : IState
{
public void handle()
{
Console.WriteLine("ConcreteStateA-----IState");
}
}
/// <summary>
/// 具体实现状态
/// </summary>
public class ConcreteStateB : IState
{
public void handle()
{
Console.WriteLine("ConcreteStateB-----IState");
}
}
3.状态上下文
代码如下(示例):状态上下文,封装状态切换以及执行状态抽象的操作,实现面向对象的多态。
/// <summary>
/// 状态上下文
/// </summary>
public class Context
{
private static IState stateA = new ConcreteStateA();
private static IState stateB = new ConcreteStateB();
public IState currentState = stateA;
/// <summary>
/// 修改当前状态,切换状态方法实现组
/// </summary>
/// <param name="state"></param>
public void setState(IState state)
{
this.currentState = state;
}
/// <summary>
/// 动态调用各个状态的操作;
/// </summary>
public void handle()
{
this.currentState.handle();
}
}
4. 调用客户端
代码如下(示例): 调用客户端
/// <summary>
/// 调用客户端
/// </summary>
public class StateClienter
{
public void clientMain()
{
var context = new Context();
Console.WriteLine("打印初始值");
context.handle();
context.setState(new ConcreteStateB());
Console.WriteLine("开始切换ConcreteStateB");
context.handle();
context.setState(new ConcreteStateA());
Console.WriteLine("开始切换ConcreteStateA");
context.handle();
}
}
5.代码输出
打印初始值
ConcreteStateA-----IState
开始切换ConcreteStateB
ConcreteStateB-----IState
开始切换ConcreteStateA
ConcreteStateA-----IState
总结
优点:
- 结构清晰,将状态独立为类,提高代码可维护性,
- 将状态转换显示化,以不同类之间的切换来实现转化
- 状态职责明确,具备扩展性。
缺点:
- 如果一个事件具有很多状态,会造成状态太多
- 状态模式的结构与实现都较为复杂,如果使用不当,会导致程序结构和代码的混乱。