状态模式(State)

简介: 结构UML.png模式的组成环境类(Context): 定义客户感兴趣的接口。维护一个ConcreteState子类的实例,这个实例定义当前状态。

结构

img_f4ab40273c179f20401c47bbbdad78fd.png
UML.png

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

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

  if (light=='红灯')
  {
    Console.WriteLine("红灯");
  }else if (light=='绿灯')
   {
      Console.WriteLine("绿灯");
    }
  else 
  {
       Console.WriteLine("黄灯");  
     }

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

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

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

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

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

信号灯抽象类

    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);
    }

具体状态类

三种颜色的信号灯实现

  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();
        }
    }

环境类

信号灯控制

    /// <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中分离出来,不同颜色的类完成自己的功能,实现了业务逻辑的分离。

输出

    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();
        }
    }
img_0f52dd3a727fc25cd078b33b16958ee1.png
show.png

重要点解析

抽象基类中重要的一个接口
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();
}

img_cd370d83a7ce97b74e58fe31d4fdadfc.png
解析.png
目录
相关文章
|
16天前
|
设计模式
设计模式之 State(状态模式)
设计模式之 State(状态模式)
10 0
|
3月前
|
设计模式 程序员
设计模式-状态模式(State)
设计模式-状态模式(State)
38 0
|
6月前
|
设计模式
设计模式19 - 状态模式【State Pattern】
设计模式19 - 状态模式【State Pattern】
19 0
|
6月前
|
设计模式
设计模式~状态模式(state)-23
在状态模式(State Pattern)中,类的行为是基于它的状态改变的。这种类型的设计模式属于行为型模式。在状态模式中,我们创建表示各种状态的对象和一个行为随着状态对象改变而改变的context对象。 目录 (1)优点: (2)缺点: (3)使用场景: (4)注意事项: (5)应用实例: 代码
25 1
|
9月前
状态模式(State)
状态模式(State)
101 0
|
11月前
|
设计模式 Java
Java设计模式-状态模式(State)
Java设计模式-状态模式(State)
|
设计模式 Java 编译器
设计模式学习(五):State状态模式
在面向对象编程中,是用类表示对象的。也就是说,程序的设计者需要考虑用类来表示什么东西。类对应的东西可能存在于真实世界中,也可能不存在于真实世界中。
113 0
设计模式学习(五):State状态模式
|
设计模式 存储
行为型-State
在实际的软件开发中,状态模式并不是很常用,但是在能够用到的场景里,它可以发挥很大的作用。从这一点上来看,它有点像我们之前讲到的组合模式。 状态模式一般用来实现状态机,而状态机常用在游戏、工作流引擎等系统开发中。不过,状态机的实现方式有多种,除了状态模式,比较常用的还有分支逻辑法和查表法。今天,我们就详细讲讲这几种实现方式,并且对比一下它们的优劣和应用场景。
120 0
行为型-State
|
设计模式 Java
浅谈JAVA设计模式之——状态模式(State)
定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
130 0
浅谈JAVA设计模式之——状态模式(State)