设计模式 之 状态模式

来源:互联网 发布:租用网络服务器多少钱 编辑:程序博客网 时间:2024/06/17 00:26

前传:

一个类内部存在多个条件分支时,你应该想一下,是不是可以用状态模式给替换。

那什么是状态模式呀?

state 把对象的内部状态独立出来,封装内部状态变化。

实现:

那怎么封装呀?想想应该有两个类:主类,辅助类(即状态类)。

主类开始得有一个状态呀。激发状态变化,但实现状态变化的细节,却通过状态类来实现。

状态类修改主类的状态。根据主类的当前状态指定主类(跳转)到下一状态类。

主类和状态类的双向互动:主类通过函数推动状态类变化;状态类负责修改主类的状态。

用户根本就不知道状态类的存在。只有程序员才知道具体的实现。(这也是传说中的“封装”)


关键词:

封装 内部状态


网上一个兄弟的例子很说明问题:
<p style="margin: 10px auto; padding-top: 0px; padding-bottom: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; font-size: 14px; line-height: 25px; ">电灯有两个状态,开(亮)与关(不亮),下面就用状态模式来实现对电灯的控制。</p><p style="margin: 10px auto; padding-top: 0px; padding-bottom: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; font-size: 14px; line-height: 25px; ">  类图</p><p style="margin: 10px auto; padding-top: 0px; padding-bottom: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; font-size: 14px; line-height: 25px; ">  <img src="http://pic002.cnblogs.com/images/2012/155937/2012071614433983.png" alt="" style="margin: 0px; padding: 0px; border: 0px; " /></p><p style="margin: 10px auto; padding-top: 0px; padding-bottom: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; font-size: 14px; line-height: 25px; ">  实现代码</p><div class="cnblogs_code" style="margin: 5px 0px; padding: 5px; background-color: rgb(245, 245, 245); font-family: 'Courier New' !important; border: 1px solid rgb(204, 204, 204); overflow: auto; "><div class="cnblogs_code_toolbar" style="margin: 5px 0px 0px; padding: 0px; "><span class="cnblogs_code_copy" style="margin: 0px; padding: 0px 5px 0px 0px; line-height: 1.8; "><a target=_blank href="http://www.cnblogs.com/wangjq/archive/2012/07/16/2593485.html" title="复制代码" style="margin: 0px; padding: 0px; text-decoration: none; color: rgb(0, 0, 0); border: none !important; "><img src="http://common.cnblogs.com/images/copycode.gif" alt="复制代码" style="margin: 0px; padding: 0px; border: none !important; " /></a></span></div><pre style="margin-top: 0px; margin-bottom: 0px; padding: 0px; white-space: pre-wrap; word-wrap: break-word; font-family: 'Courier New' !important; ">    <span style="margin: 0px; padding: 0px; line-height: 1.8; color: rgb(128, 128, 128); ">///</span> <span style="margin: 0px; padding: 0px; line-height: 1.8; color: rgb(128, 128, 128); "><summary></span>    <span style="margin: 0px; padding: 0px; line-height: 1.8; color: rgb(128, 128, 128); ">///</span><span style="margin: 0px; padding: 0px; line-height: 1.8; color: rgb(0, 128, 0); "> 电灯类,对应模式中的Context类    </span><span style="margin: 0px; padding: 0px; line-height: 1.8; color: rgb(128, 128, 128); ">///</span> <span style="margin: 0px; padding: 0px; line-height: 1.8; color: rgb(128, 128, 128); "></summary></span>    <span style="margin: 0px; padding: 0px; line-height: 1.8; color: rgb(0, 0, 255); ">public</span> <span style="margin: 0px; padding: 0px; line-height: 1.8; color: rgb(0, 0, 255); ">class</span><span style="margin: 0px; padding: 0px; line-height: 1.8; "> Light    {        </span><span style="margin: 0px; padding: 0px; line-height: 1.8; color: rgb(0, 0, 255); ">private</span><span style="margin: 0px; padding: 0px; line-height: 1.8; "> LightState state;        </span><span style="margin: 0px; padding: 0px; line-height: 1.8; color: rgb(0, 0, 255); ">public</span><span style="margin: 0px; padding: 0px; line-height: 1.8; "> Light(LightState state)        {            </span><span style="margin: 0px; padding: 0px; line-height: 1.8; color: rgb(0, 0, 255); ">this</span>.state =<span style="margin: 0px; padding: 0px; line-height: 1.8; "> state;        }        </span><span style="margin: 0px; padding: 0px; line-height: 1.8; color: rgb(128, 128, 128); ">///</span> <span style="margin: 0px; padding: 0px; line-height: 1.8; color: rgb(128, 128, 128); "><summary></span>        <span style="margin: 0px; padding: 0px; line-height: 1.8; color: rgb(128, 128, 128); ">///</span><span style="margin: 0px; padding: 0px; line-height: 1.8; color: rgb(0, 128, 0); "> 按下电灯开关        </span><span style="margin: 0px; padding: 0px; line-height: 1.8; color: rgb(128, 128, 128); ">///</span> <span style="margin: 0px; padding: 0px; line-height: 1.8; color: rgb(128, 128, 128); "></summary></span>        <span style="margin: 0px; padding: 0px; line-height: 1.8; color: rgb(0, 0, 255); ">public</span> <span style="margin: 0px; padding: 0px; line-height: 1.8; color: rgb(0, 0, 255); ">void</span><span style="margin: 0px; padding: 0px; line-height: 1.8; "> PressSwich()        {            state.PressSwich(</span><span style="margin: 0px; padding: 0px; line-height: 1.8; color: rgb(0, 0, 255); ">this</span><span style="margin: 0px; padding: 0px; line-height: 1.8; ">);        }        </span><span style="margin: 0px; padding: 0px; line-height: 1.8; color: rgb(0, 0, 255); ">public</span><span style="margin: 0px; padding: 0px; line-height: 1.8; "> LightState State        {            </span><span style="margin: 0px; padding: 0px; line-height: 1.8; color: rgb(0, 0, 255); ">get</span> { <span style="margin: 0px; padding: 0px; line-height: 1.8; color: rgb(0, 0, 255); ">return</span><span style="margin: 0px; padding: 0px; line-height: 1.8; "> state; }            </span><span style="margin: 0px; padding: 0px; line-height: 1.8; color: rgb(0, 0, 255); ">set</span> { state =<span style="margin: 0px; padding: 0px; line-height: 1.8; "> value; }        }        }    </span><span style="margin: 0px; padding: 0px; line-height: 1.8; color: rgb(128, 128, 128); ">///</span> <span style="margin: 0px; padding: 0px; line-height: 1.8; color: rgb(128, 128, 128); "><summary></span>    <span style="margin: 0px; padding: 0px; line-height: 1.8; color: rgb(128, 128, 128); ">///</span><span style="margin: 0px; padding: 0px; line-height: 1.8; color: rgb(0, 128, 0); "> 抽象的电灯状态类,相当于State类    </span><span style="margin: 0px; padding: 0px; line-height: 1.8; color: rgb(128, 128, 128); ">///</span> <span style="margin: 0px; padding: 0px; line-height: 1.8; color: rgb(128, 128, 128); "></summary></span>    <span style="margin: 0px; padding: 0px; line-height: 1.8; color: rgb(0, 0, 255); ">public</span> <span style="margin: 0px; padding: 0px; line-height: 1.8; color: rgb(0, 0, 255); ">abstract</span> <span style="margin: 0px; padding: 0px; line-height: 1.8; color: rgb(0, 0, 255); ">class</span><span style="margin: 0px; padding: 0px; line-height: 1.8; "> LightState    {        </span><span style="margin: 0px; padding: 0px; line-height: 1.8; color: rgb(0, 0, 255); ">public</span> <span style="margin: 0px; padding: 0px; line-height: 1.8; color: rgb(0, 0, 255); ">abstract</span> <span style="margin: 0px; padding: 0px; line-height: 1.8; color: rgb(0, 0, 255); ">void</span><span style="margin: 0px; padding: 0px; line-height: 1.8; "> PressSwich(Light light);    }    </span><span style="margin: 0px; padding: 0px; line-height: 1.8; color: rgb(128, 128, 128); ">///</span> <span style="margin: 0px; padding: 0px; line-height: 1.8; color: rgb(128, 128, 128); "><summary></span>    <span style="margin: 0px; padding: 0px; line-height: 1.8; color: rgb(128, 128, 128); ">///</span><span style="margin: 0px; padding: 0px; line-height: 1.8; color: rgb(0, 128, 0); "> 具体状态类, 开    </span><span style="margin: 0px; padding: 0px; line-height: 1.8; color: rgb(128, 128, 128); ">///</span> <span style="margin: 0px; padding: 0px; line-height: 1.8; color: rgb(128, 128, 128); "></summary></span>    <span style="margin: 0px; padding: 0px; line-height: 1.8; color: rgb(0, 0, 255); ">public</span> <span style="margin: 0px; padding: 0px; line-height: 1.8; color: rgb(0, 0, 255); ">class</span><span style="margin: 0px; padding: 0px; line-height: 1.8; "> On : LightState    {        </span><span style="margin: 0px; padding: 0px; line-height: 1.8; color: rgb(128, 128, 128); ">///</span> <span style="margin: 0px; padding: 0px; line-height: 1.8; color: rgb(128, 128, 128); "><summary></span>        <span style="margin: 0px; padding: 0px; line-height: 1.8; color: rgb(128, 128, 128); ">///</span><span style="margin: 0px; padding: 0px; line-height: 1.8; color: rgb(0, 128, 0); "> 在开状态下,按下开关则切换到关的状态。        </span><span style="margin: 0px; padding: 0px; line-height: 1.8; color: rgb(128, 128, 128); ">///</span> <span style="margin: 0px; padding: 0px; line-height: 1.8; color: rgb(128, 128, 128); "></summary></span>        <span style="margin: 0px; padding: 0px; line-height: 1.8; color: rgb(128, 128, 128); ">///</span> <span style="margin: 0px; padding: 0px; line-height: 1.8; color: rgb(128, 128, 128); "><param name="light"></param></span>        <span style="margin: 0px; padding: 0px; line-height: 1.8; color: rgb(0, 0, 255); ">public</span> <span style="margin: 0px; padding: 0px; line-height: 1.8; color: rgb(0, 0, 255); ">override</span> <span style="margin: 0px; padding: 0px; line-height: 1.8; color: rgb(0, 0, 255); ">void</span><span style="margin: 0px; padding: 0px; line-height: 1.8; "> PressSwich(Light light)        {            Console.WriteLine(</span><span style="margin: 0px; padding: 0px; line-height: 1.8; color: rgb(128, 0, 0); ">"</span><span style="margin: 0px; padding: 0px; line-height: 1.8; color: rgb(128, 0, 0); ">Turn off the light.</span><span style="margin: 0px; padding: 0px; line-height: 1.8; color: rgb(128, 0, 0); ">"</span><span style="margin: 0px; padding: 0px; line-height: 1.8; ">);            light.State </span>= <span style="margin: 0px; padding: 0px; line-height: 1.8; color: rgb(0, 0, 255); ">new</span><span style="margin: 0px; padding: 0px; line-height: 1.8; "> Off();        }    }    </span><span style="margin: 0px; padding: 0px; line-height: 1.8; color: rgb(128, 128, 128); ">///</span> <span style="margin: 0px; padding: 0px; line-height: 1.8; color: rgb(128, 128, 128); "><summary></span>    <span style="margin: 0px; padding: 0px; line-height: 1.8; color: rgb(128, 128, 128); ">///</span><span style="margin: 0px; padding: 0px; line-height: 1.8; color: rgb(0, 128, 0); "> 具体状态类,关    </span><span style="margin: 0px; padding: 0px; line-height: 1.8; color: rgb(128, 128, 128); ">///</span> <span style="margin: 0px; padding: 0px; line-height: 1.8; color: rgb(128, 128, 128); "></summary></span>    <span style="margin: 0px; padding: 0px; line-height: 1.8; color: rgb(0, 0, 255); ">public</span> <span style="margin: 0px; padding: 0px; line-height: 1.8; color: rgb(0, 0, 255); ">class</span><span style="margin: 0px; padding: 0px; line-height: 1.8; "> Off: LightState    {        </span><span style="margin: 0px; padding: 0px; line-height: 1.8; color: rgb(128, 128, 128); ">///</span> <span style="margin: 0px; padding: 0px; line-height: 1.8; color: rgb(128, 128, 128); "><summary></span>        <span style="margin: 0px; padding: 0px; line-height: 1.8; color: rgb(128, 128, 128); ">///</span><span style="margin: 0px; padding: 0px; line-height: 1.8; color: rgb(0, 128, 0); "> 在关状态下,按下开关则打开电灯。        </span><span style="margin: 0px; padding: 0px; line-height: 1.8; color: rgb(128, 128, 128); ">///</span> <span style="margin: 0px; padding: 0px; line-height: 1.8; color: rgb(128, 128, 128); "></summary></span>        <span style="margin: 0px; padding: 0px; line-height: 1.8; color: rgb(128, 128, 128); ">///</span> <span style="margin: 0px; padding: 0px; line-height: 1.8; color: rgb(128, 128, 128); "><param name="light"></param></span>        <span style="margin: 0px; padding: 0px; line-height: 1.8; color: rgb(0, 0, 255); ">public</span> <span style="margin: 0px; padding: 0px; line-height: 1.8; color: rgb(0, 0, 255); ">override</span> <span style="margin: 0px; padding: 0px; line-height: 1.8; color: rgb(0, 0, 255); ">void</span><span style="margin: 0px; padding: 0px; line-height: 1.8; "> PressSwich(Light light)        {            Console.WriteLine(</span><span style="margin: 0px; padding: 0px; line-height: 1.8; color: rgb(128, 0, 0); ">"</span><span style="margin: 0px; padding: 0px; line-height: 1.8; color: rgb(128, 0, 0); ">Turn on the light.</span><span style="margin: 0px; padding: 0px; line-height: 1.8; color: rgb(128, 0, 0); ">"</span><span style="margin: 0px; padding: 0px; line-height: 1.8; ">);            light.State </span>= <span style="margin: 0px; padding: 0px; line-height: 1.8; color: rgb(0, 0, 255); ">new</span><span style="margin: 0px; padding: 0px; line-height: 1.8; "> On();        }    }</span>
复制代码

 客户端代码

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


0 0