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

本文共 4111 字,大约阅读时间需要 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://www.cnblogs.com/wangjq/archive/2012/07/16/2593485.html

 

转载于:https://www.cnblogs.com/liujun5020/p/5439143.html

你可能感兴趣的文章
[BZOJ4303]数列
查看>>
一般处理程序在VS2012中打开问题
查看>>
C语言中的++和--
查看>>
thinkphp3.2.3入口文件详解
查看>>
POJ 1141 Brackets Sequence
查看>>
Ubuntu 18.04 root 使用ssh密钥远程登陆
查看>>
Servlet和JSP的异同。
查看>>
虚拟机centOs Linux与Windows之间的文件传输
查看>>
ethereum(以太坊)(二)--合约中属性和行为的访问权限
查看>>
IOS内存管理
查看>>
middle
查看>>
[Bzoj1009][HNOI2008]GT考试(动态规划)
查看>>
Blob(二进制)、byte[]、long、date之间的类型转换
查看>>
OO第一次总结博客
查看>>
day7
查看>>
iphone移动端踩坑
查看>>
vs无法加载项目
查看>>
Beanutils基本用法
查看>>
玉伯的一道课后题题解(关于 IEEE 754 双精度浮点型精度损失)
查看>>
《BI那点儿事》数据流转换——百分比抽样、行抽样
查看>>