用Strategy替换条件逻辑

 

         首先说明一下标题,Strategy即为策略模式。本文主要介绍的使用策略模式解决实际项目中过多if-else条件判断。下面给出一个题目,然后看看原始的使用if-else的解决方法存在些什么问题。题目如下:

      实现一个游戏中普通小怪的的行为。如果小怪周围60像素之内没有玩家出现,那么它就自己走走停停的闲逛。如果60像素范围之内出现了玩家,那它就会追赶玩家。如果和玩家的距离小于20像素,就攻击一下玩家,然后重新判断条件。

      下面就给出这个问题的if-else版本的代码实现:

(1)首先定义一个游戏地图类,这个类中提供了一个玩家,并能够获得玩家和指定小怪的距离。

 

(2)接下来给出小怪的类

 

      对于这个例子,上述代码还算简洁,如果添加更多种情况,比如说距离为20-40之间做事情a,60-80之间做事情b等。随着情况的增多,状态判断函数的if-else数量就会随着增加,代码的可读性和扩展性也急剧下降。从代码的实现中我们发现,action方法所作的,就是根据不同的状态(与玩家的距离)来执行不同的行为,要么溜达;要么追赶;要么攻击。问题的本质就在于:根据不同的条件执行不同的算法(这里就是攻击了)从而就引出了今天所说的重构:【用Strategy替换条件逻辑】。

     下面就先介绍一下【用Strategy替换条件逻辑】重构

     适用范围方法中条件逻辑控制着应该执行计算的哪个变体。

     解决方法为每一个变体创建一个Strategy并使方法把计算委托到Strategy实例。

     动机Martin Flower指出,程序之中复杂的条件逻辑是最常导致复杂度上升的地点之一。条件逻辑往往用来确定应该使用算法的哪个变体。Strategy模式可以帮助我们管理由于算法的过多变体而产生的复杂度。

     现在,我们就开始重构上面的问题代码!

(1)搜索上面代码中的臭味!根据Martin给出的重构目录,我们发现Bug类的action()方法中有个swtich语句。它根据类型码来选择bug的行为。哈哈,找到目标了!关于类型码的重构,有两种方式:用子类替换类型码和用State/Strategy来替换类型码。因为运行期间类型码会发生变化,所以选择用State/Strategy来替换类型码,在这里Strategy更合适。

(2)发现臭味就得清除!下面就按照Martin的指点,一步步的清除臭味。

     首先是封装类型码字段,在这里情况比较特殊,类型码字段就是getState()。现在就创建一个抽象的状态类,并提供一个返回类型码的抽象方法。并为每个类型码创建一个子类。代码如下:

 

     然后修改Bug类中的_bugAction字段的封装方法

 

     通常情况下,需要将类型码从Bug类转移至抽象类BugAction。这时,我们就将类型码使用多态替代了。现在有了这样一个继承结构,就可以进行下一步重构。

     现在有一个潜在的问题,就是BugAction对象的创建。程序中需要根据小怪与玩家的距离来创建相应的BugAction,如果有更多的BugAction类型,那么setState()方法中的if-else语句就会更长,解决方法就是将其提取出来为一个Factory。

     BugAction在这里是一个策略类,然而现在还没有具体的功能(这里应该就是小怪的行为了)。那么马上给它添加。在父类中创建一个抽象方法,然后子类分别给出实现。现在给出重构完的实现代码:

Bug类:

 

BugActionFactory类:

BugAction及其子类:

       最后得到了这样的结构。面对新的变化,也就是对于新的条件有新的行为。怎么办?扩展一个BugAction的子类,然后在action()方法中执行相应的操作,然后修改BugActionFactory类,提供创建新的BugAction。这也符合了软件开发的OCP原则,对扩展开发,对修改封闭。但是程序中也对现有的代码进行了修改,那又怎样解释呢?现实中没有完全符合原则的情况,只有接近。想一想吧,在新需求到来的时候,该对程序的哪一部分进行修改一目了然。程序的可读性明显提升,那些使用Bug类的客户代码也无需任何改动!事情挺完美的,呵呵(在我现在看来)

       这篇文章写的有点乱,从最开始构思为使用状态模式。但是在重构的过程中发现策略模式更加适合。这样我也就更加深入的理解了《重构与模式》的思想了,模式不是一开始设定好的,而是通过重构逐渐的接近的。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值