设计模式学习总结状态模式(State Method)

问题:
在面向对象软件设计时,常常碰到某一个对象由于状态的不同而有不同的行为。我们可以采用switch…case语句来解决问题,但是,如果这种状态变化比较频繁(状态的数量会变化),状态、判断逻辑、行为耦合在一起,当系统中需要加入新的状态时,必须修改判断逻辑(加入新的case...)。

定义:
状态模式(State Pattern)是一种行为模式。当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。

意图:
定义一个Context,接收客户端配置的具体状态对象,并将与状态相关的请求委托给当前的ConcreteState对象处理,并将Context自身作为一个参数传递给处理该请求的状态对象,这使得状态对象在执行完成后,可以访问context修改状态(也可以由context控制修改)。State模式把状态的判断逻辑转移到表示不同状态的一系列类中,所有与一个特定状态相关的行为都放入每个单独的类中,使得复杂的判断逻辑简单化,并达到了解耦的目的。

参与者:
•环境(Context)角色:维护一个ConcreteState子类的一个实例,这个实例定义当前的状态。
•状态(State)角色:抽象状态类,定义一个接口以封装与Context的一个特定状态相关的行为。
•具体状态(ConcreteState)角色:每一个子类实现一个与Context的一个状态相关的行为。 

UML:

代码说明:

/// <summary>
/// Context类,维护一个ConcreteState子类的实例,这个实例定义当前的状态。
/// </summary>
public class Context
{
    /// <summary>
    
/// 存储状态
    
/// </summary>
    public StateClass State { getset; }

    /// <summary>
    
/// 定义Context的初始状态
    
/// </summary>
    
/// <param name="state"></param>
    public Context(StateClass state)
    {
        this.State = state;
    }

    /// <summary>
    
/// 对请求做处理
    
/// </summary>
    public void Request()
    {
        //将当前对象作为参数传递给具体的State
        State.Handle(this);
    }
}
/// <summary>
/// 抽象状态类,定义一个接口以封装与Context的一个特定状态相关的行为
/// </summary>
public abstract class StateClass
{
    public abstract void Handle(Context context);
}

/// <summary>
/// 具体状态类,每一个子类实现一个与Context的一个状态相关的行为
/// </summary>
public class ConcreteStateA : StateClass
{
    /// <summary>
    
/// 设置ConcreteStateA的下一个状态是ConcreteStateB
    
/// </summary>
    
/// <param name="context"></param>
    public override void Handle(Context context)
    {
        Console.WriteLine("当前状态是 A.");
        context.State = new ConcreteStateB();
    }
}

public class ConcreteStateB : StateClass
{
    /// <summary>
    
/// 设置ConcreteStateB的下一个状态是ConcreteSateA
    
/// </summary>
    
/// <param name="context"></param>
    public override void Handle(Context context)
    {
        Console.WriteLine("当前状态是 B.");
        context.State = new ConcreteStateA();
    }        
}
/// <summary>
/// 客户端测试代码
/// </summary>
public void StateTest()
{
    //初始化一个状态
    Context Context = new Context(new ConcreteStateA());
    //执行请求,并修改状态。
    Context.Request();
    //执行请求,并修改状态。
    Context.Request();
    //执行请求,并修改状态。
    Context.Request();
}

优点:
•状态模式把各种状态转移逻辑分布到一系列State的子类中,来减少相互间的依赖。
•所有状态相关的行为都放在某个ConcereteState中,通过定义新的ConcereteState很容易地增加新的状态和转换。
缺点:
•状态的转换被定义在concreteState或context中,也就是说由concreteState或context决定下一个状态,状态的插入仍需要修改代码
适用场合:
•当一个对象的行为取决于它的状态,并且它必须在运行时刻根据状态改变它的行为时,就可以考虑使用状态模式来。
•一个操作中含有庞大的分支结构,并且这些分支决定于对象的状态。

与策略模式区别:
策略模式关注行为的变化,但归根结底只有一个行为,变化的只是行为的实现.客户不关注这些.当新增变化时对客户可以没有任何影响.
状态模式同样关注行为的变化,但这个变化是由状态来驱动,一般来说每个状态和行为都不同.新增的状态或行为一般与已有的不同,客户需要关注这些变化.

状态模式中State及其子类中的操作都将Context传入作为参数,以便State可以通过这个指针调用Context中的方法,修改状态。而策略模式没有。

原文地址:https://www.cnblogs.com/ejiyuan/p/2608462.html