用State替换状态改变条件语句

      State模式定义:不同的状态,不同的行为;或者说每一个状态都有不同的行为。

      State模式使用场合:State模式在实际使用中用的比较多,主要用于“状态的切换”。如果针对状态的if-else切换反复出现,应该考虑使用State模式。不只是根据状态,也有根据属性。如果对象属性不同,行为也就不同了。

      下面,给出一个小的例题来说明问题:

      十字路口红绿灯问题。根据灯的颜色输出相关的提示信息。代码如下:

      

      现在看一下问题所在:关于对象状态的判断逻辑散落在整个类中。在这里,getStateInfo()和nextState()方法都对类状态进行判断后才给出相应的处理方式。对于红绿灯这类状态比较少的问题处理采用这种方式尚可,如果状态比较多的话问题就比较严重了。这里问题的本质是:不同的状态有不同的行为。从而引出今天的重构:【用State替换状态改变条件语句】。

      下面就来简单的介绍一下【用State替换状态改变条件语句】重构。

      适用范围:控制一个对象状态转换的条件表达式过于复杂。

      解决方法:用处理特殊状态和状态转换的State类替换条件语句。

      动机:重构实现State模式的主要原因:是为了对付过度复杂的状态改变条件逻辑,这种逻辑往往会散步在整个类中,控制对象的状态以及状态之间的转换。

      在State模式中,需要创建代表对象特殊状态和状态间转换的类。包含状态改变的对象称为上下文。上下文把状态相关的行为委托到状态对象上。通过上下文引用不同的状态对象,状态对象可以在运行时实现状态转换。

      把状态改变条件逻辑从类中去除,并搬移到表示不同状态的一系列类中,可以产生更简单的设计,它提供了观察状态转换的更好的鸟瞰图。另一方面,如果类中的状态转换逻辑很容易理解,就不需要重构到State模式了。

      现在,看一下本重构的优缺点:

      优点:

  • 减少或去除状态改变条件逻辑
  • 简化了复杂的状态改变逻辑
  • 提供了观察状态改变的很好的鸟瞰图

      缺点:

  • 当状态转换逻辑已经易于理解的时候,会增加设计的复杂度

      接下来,就将上述的红绿灯问题重构到State模式。

      1.首先,使用【用类替换类型码】重构。将Cross类中的类型码提取称为一个类。关于【用类替换类型码】重构,在这里不多复述,见另一篇blog:http://blog.csdn.net/prince2270/archive/2009/09/10/4540677.aspx。在State模式中,上下文类被描述为"State:Context",状态超类被描述为"State:State"。重构后的结果如下:

        Cross类:

         

        State类(从类型码中提取出来的类):

           

      2.状态超类State中的每个常量都引用着状态超类的一个实例。应用【提取子类】重构,为每个常量产生一个子类(描述为State:ConcreateState),然后更新超类中的常量,使它们引用相应的子类实例。最后,把状态超类设置为抽象类。     

        State类:

          

        State子类:

          

      3.在上下文类中找出根据状态转换逻辑来修改原始状态字段的方法。把这个方法复制到状态超类中,在修改最少的前提下是这个新方法可以运行。(一个常用的、简单的修改是把上下文类传入这个方法,以便新方法中的代码调用上下文类的方法)。最后,把上下文类中方法的方法体替换为对新方法的委托。

        对上下文类中的每个根据状态转换逻辑来修改原始状态子uand方法重复这一步骤。

        State类:

        

       Cross类:

         

     4.选择上下文类能够进入的状态,然后识别出状态超类中的哪些方法会是这个状态转换到其他状态。把这些识别出来的方法复制到与被选中的状态相关联的子类中,并去除无关的逻辑。最后删除状态超类中的方法实现。

       State类:

         

      State子类:

        

     最后,程序得到了这样的结构,去除了程序中的if-else判断语句,是程序中状态改变的流程更加清晰。但也有一些副作用:原来在一个类中可以实现的功能,现在却需要五个类来完成。增加了程序结构的复杂性。

 

            

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值