zoukankan      html  css  js  c++  java
  • 设计模式学习总结状态模式(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中的方法,修改状态。而策略模式没有。

  • 相关阅读:
    PHP PSR 标准规范
    PHP线程安全与非线程安全的区别(NTS/TS)选择?
    goto 语法在 PHP 中的使用
    linux命令post请求发送json串
    接口日志表sql【我】
    sentinel最简单接入【我】
    Jps命令—使用详解
    MyBatis-Plus Wrapper条件构造器查询大全
    IDEA项目启动不起来也不打印日志【我】
    linux下查看nginx配置文件地址
  • 原文地址:https://www.cnblogs.com/ejiyuan/p/2608462.html
Copyright © 2011-2022 走看看