前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >状态模式(State)

状态模式(State)

作者头像
happlyfox
发布2018-10-31 14:52:10
4840
发布2018-10-31 14:52:10
举报
文章被收录于专栏:技术开源分享技术开源分享

结构

UML.png

模式的组成 环境类(Context): 定义客户感兴趣的接口。维护一个ConcreteState子类的实例,这个实例定义当前状态。 抽象状态类(State): 定义一个接口以封装与Context的一个特定状态相关的行为。 具体状态类(ConcreteState): 每一子类实现一个与Context的一个状态相关的行为。

本文状态模式的例子使用我们生活中的交通信号灯的例子。交通信号灯一共具有三种状态,红灯,绿灯,黄灯,在这三种状态之间相互切换。如果让我们做一个demo,得到不同的状态时的信号灯颜色,最简单的写法应该是如下

代码语言:javascript
复制
  if (light=='红灯')
  {
    Console.WriteLine("红灯");
  }else if (light=='绿灯')
   {
      Console.WriteLine("绿灯");
    }
  else 
  {
       Console.WriteLine("黄灯");  
     }

这样的写法通俗易懂,但是同时也存在着很大的问题。所有的 业务逻辑都在上端被定义,如果某一天业务逻辑修改了或者新增了呢,我们就要添加新的if条件,因为逻辑的高度集成,不可避免的bug就有可能触发,这是很不友好的,所以这样的方式实不可取的。

因为这一章节介绍的是状态模式,所以我们采用此方式来进行设计,其他的方式LZ也试过,也可以,不过如果是不同的状态之间带着关联,且不同状态拥有不同行为的,推荐状态模式,废话不多话,开始Lu代码

上面我们说到状态模式的组成分为三个: 环境类(Context) 抽象状态类(State) 具体状态类(ConcreteState) 就算有每一个的解释,我们还是不能很好的理解意思,接下来我用一个通俗的方式来说明。 还是用信号灯的例子来作为参考

抽象状态类,就是信号灯抽象类,里面包含颜色的显示接口 具体状态类,就是三个颜色的信号灯,继承信号灯抽象类,重载颜色显示接口 环境类,就是信号灯,负责切换不同信号灯状态

大同小异,如果我们的对象是电梯,我们是不是也可以 用同样的道理推断出来。接下来让我们对三个组成进行编码

信号灯抽象类

代码语言:javascript
复制
    public  enum LightColor
    {
        Green = 0,
        Yellow = 1,
        Red = 2
    }

    /// <summary>
    /// 灯基类
    /// </summary>
    public abstract class LightBase
    {
        public LightColor Color { get; set; }

        /// <summary>
        /// 展示灯状态
        /// </summary>
        public abstract void Show();

        /// <summary>
        /// 切换灯颜色
        /// </summary>
        public abstract void Turn();

        /// <summary>
        /// 切换上下文
        /// </summary>
        public abstract void TurnContext(LightContext context);
    }

具体状态类

三种颜色的信号灯实现

代码语言:javascript
复制
  public class GreenLight:LightBase
    {
        public override void Show()
        {
            Console.WriteLine("绿灯");
        }

        public override void Turn()
        {
            this.Color = LightColor.Yellow;
        }

        public override void TurnContext(LightContext context)
        {
            context.LigthBase = new YellowLight();
        }
    }

    public class RedLight : LightBase
    {
        public override void Show()
        {
            Console.WriteLine("红灯");
        }

        public override void Turn()
        {
            this.Color = LightColor.Green;
        }

        public override void TurnContext(LightContext context)
        {
            context.LigthBase = new GreenLight();
        }
    }

    public class YellowLight : LightBase
    {
        public override void Show()
        {
            Console.WriteLine("黄灯");
        }

        public override void Turn()
        {
            this.Color = LightColor.Red;
        }
       public override void TurnContext(LightContext context)
        {
            context.LigthBase = new RedLight();
        }
    }

环境类

信号灯控制

代码语言:javascript
复制
    /// <summary>
    /// 灯控制上下文
    /// </summary>
    public class LightContext
    {
        public LightBase LigthBase;

        public LightContext(LightBase lightBase)
        {
            this.LigthBase = lightBase;
        }

        /// <summary>
        /// 展示当前灯颜色
        /// </summary>
        public void Show()
        {
            this.LigthBase.Show();
        }

        /// <summary>
        /// 切换到一下个灯
        /// </summary>
        public void Turn()
        {
            this.LigthBase.TurnContext(this);
        }
    }

上面的代码,其实是对原来的一个简单的修改,将逻辑从三层if中分离出来,不同颜色的类完成自己的功能,实现了业务逻辑的分离。

输出

代码语言:javascript
复制
    public class StateShow
    {
        public static void Show()
        {
            LightBase greeBase = new GreenLight();
            LightContext context = new LightContext(greeBase);
            context.Show();
            context.Turn();

            context.Show();
            context.Turn();

            context.Show();
            context.Turn();

            Console.Read();
        }
    }

show.png

重要点解析

代码语言:javascript
复制
抽象基类中重要的一个接口
public abstract void TurnContext(LightContext context);

在具体抽象类中我们可以看到对应的实现,以YellowLight(黄灯状态举例)
public override void TurnContext(LightContext context)
{
    context.LigthBase = new RedLight();
}

通过实现接口,我们将传递的上下文进行更改。这么一来大概的意思就出来了,例如我们现在是绿灯状态,类就是GreenLight,对应的行为是Show(),如果我们想要切换到下一个状态,我们只需要将环境上下文进行切换,例如我们切换到红灯状态,那我们就可以操作红灯的行为Show()。
接下去就是环境类的说明

    /// <summary>
    /// 灯控制上下文
    /// </summary>
    public class LightContext
    {
        public LightBase LigthBase;

        public LightContext(LightBase lightBase)
        {
            this.LigthBase = lightBase;
        }

        /// <summary>
        /// 展示当前灯颜色
        /// </summary>
        public void Show()
        {
            this.LigthBase.Show();
        }

        /// <summary>
        /// 切换到一下个灯
        /// </summary>
        public void Turn()
        {
            this.LigthBase.TurnContext(this);
        }
    }

环境类的实现也很简单,我们定义了一个内部的成员变量(LightBase),因为LightBase是所有状态灯的基类,所以我们可以在LightContext上下文内部定义操作LigthBase的方法,也就是Show。 Turn方法的实现可能有些人一下子看不懂,这个实现还是有点意思的。当前LightBase执行TurnContext(参数),参数是他自身。 举一个红灯变绿灯的例子也就能看懂了

LightContext context=new LightContext(new RedLight()); 默认是红灯,我们调用 context.Turn(); 执行的其实是RedLigth 的TurnContext方法 public override void TurnContext(LightContext context) { context.LigthBase = new GreenLight(); }

解析.png

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018.08.14 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 具体状态类
  • 环境类
  • 输出
  • 重要点解析
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档