博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
设计模式学习笔记-状态模式
阅读量:4169 次
发布时间:2019-05-26

本文共 4004 字,大约阅读时间需要 13 分钟。

原文链接:

 

1. 概述

  当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。

2. 解决的问题

  主要解决的是当控制一个对象状态转换的条件表达式过于复杂时的情况。把状态的判断逻辑转移到表示不同的一系列类当中,可以把复杂的逻辑判断简单化。

3. 模式中的角色

  3.1 上下文环境(Context):它定义了客户程序需要的接口并维护一个具体状态角色的实例,将与状态相关的操作委托给当前的Concrete State对象来处理。

  3.2 抽象状态(State):定义一个接口以封装使用上下文环境的的一个特定状态相关的行为。

  3.3 具体状态(Concrete State):实现抽象状态定义的接口。

4. 模式解读

  4.1 状态模式的类图

  

  4.2 状态模式的代码实现

///     /// Context类,维护一个ConcreteState子类的实例,这个实例定义当前的状态。    ///     public class Context    {        private State state;        ///         /// 定义Context的初始状态        ///         ///         public Context(State state)        {            this.state = state;        }        ///         /// 可读写的状态属性,用于读取和设置新状态        ///         public State State        {            get { return state; }            set { state = value; }        }        ///         /// 对请求做处理,并设置下一个状态        ///         public void Request()        {            state.Handle(this);        }    }    ///     /// 抽象状态类,定义一个接口以封装与Context的一个特定状态相关的行为    ///     public abstract class State    {        public abstract void Handle(Context context);    }    ///     /// 具体状态类,每一个子类实现一个与Context的一个状态相关的行为    ///     public class ConcreteStateA : State    {        ///         /// 设置ConcreteStateA的下一个状态是ConcreteStateB        ///         ///         public override void Handle(Context context)        {            Console.WriteLine("当前状态是 A.");            context.State = new ConcreteStateB();        }    }    public class ConcreteStateB : State    {        ///         /// 设置ConcreteStateB的下一个状态是ConcreteSateA        ///         ///         public override void Handle(Context context)        {            Console.WriteLine("当前状态是 B.");            context.State = new ConcreteStateA();        }    }

  4.3 客户端调用

class Program    {        static void Main(string[] args)        {            // 设置Context的初始状态为ConcreteStateA            Context context = new Context(new ConcreteStateA());            // 不断地进行请求,同时更改状态            context.Request();            context.Request();            context.Request();            context.Request();            Console.Read();        }    }

  运行结果

  

5. 模式总结

  5.1 优点

    5.1.1 状态模式将与特定状态相关的行为局部化,并且将不同状态的行为分割开来。

    5.1.2 所有状态相关的代码都存在于某个ConcereteState中,所以通过定义新的子类很容易地增加新的状态和转换。

    5.1.3 状态模式通过把各种状态转移逻辑分不到State的子类之间,来减少相互间的依赖。

  5.2 缺点

    5.2.1 导致较多的ConcreteState子类

  5.3 适用场景

    5.3.1 当一个对象的行为取决于它的状态,并且它必须在运行时刻根据状态改变它的行为时,就可以考虑使用状态模式来。

    5.3.2 一个操作中含有庞大的分支结构,并且这些分支决定于对象的状态。

6. 应用举例:电灯有两个状态,开(亮)与关(不亮),下面就用状态模式来实现对电灯的控制。

  6.1 类图

  

  6.2 实现代码

///     /// 电灯类,对应模式中的Context类    ///     public class Light    {        private LightState state;        public Light(LightState state)        {            this.state = state;        }        ///         /// 按下电灯开关        ///         public void PressSwich()        {            state.PressSwich(this);        }        public LightState State        {            get { return state; }            set { state = value; }        }        }    ///     /// 抽象的电灯状态类,相当于State类    ///     public abstract class LightState    {        public abstract void PressSwich(Light light);    }    ///     /// 具体状态类, 开    ///     public class On : LightState    {        ///         /// 在开状态下,按下开关则切换到关的状态。        ///         ///         public override void PressSwich(Light light)        {            Console.WriteLine("Turn off the light.");            light.State = new Off();        }    }    ///     /// 具体状态类,关    ///     public class Off: LightState    {        ///         /// 在关状态下,按下开关则打开电灯。        ///         ///         public override void PressSwich(Light light)        {            Console.WriteLine("Turn on the light.");            light.State = new On();        }    }

  6.3 客户端代码

class Program    {        static void Main(string[] args)        {            // 初始化电灯,原始状态为关            Light light = new Light(new Off());            // 第一次按下开关,打开电灯            light.PressSwich();            // 第二次按下开关,关闭电灯            light.PressSwich();            Console.Read();        }    }

  执行结果

  

转载地址:http://llkai.baihongyu.com/

你可能感兴趣的文章
Visual Studio 2005调试程序时老是提示"生成“cmd.exe”时出错".
查看>>
vs2005快捷键
查看>>
Server-push技术(comet)----------asp.net中的异步处理+client与服务器端的长连接
查看>>
cannot open include file 'afxres.rc'
查看>>
MFC为简单对话框程序添加菜单并加上响应事件
查看>>
error LNK2001: unresolved external symbol "protected: void __thiscall
查看>>
Eric4安装
查看>>
android解析XML
查看>>
Java加密技术
查看>>
qt4:读取 access 数据库
查看>>
SQL语句进行插入
查看>>
QWidget QMainWindow QDialog 之间的区别
查看>>
QT Designer
查看>>
C++中this指针的用法.
查看>>
QT中的元对象系统
查看>>
Vc中得combox的使用
查看>>
Myeclipse8.6集成jBPM4.4插件
查看>>
MyEclipse插件安装
查看>>
JSF
查看>>
关于Struts+JBPM+Hibernate+MYsql的结合
查看>>