设计模式 之 状态模式

前传:

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

那什么是状态模式呀?

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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值