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

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

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

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

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

UML:

设计模式学习总结-状态模式(State Method)_第1张图片

代码说明:

///   <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中的方法,修改状态。而策略模式没有。

你可能感兴趣的:(设计模式学习总结-状态模式(State Method))