设计模式学习_策略设计模式


          将行为抽象封装。    
                      ——策略设计模式

         案例:模拟一款鸭子游戏,游戏中随着版本的迭代,可能会出现各种鸭子:会游泳的,会飞的,会叫或者即会飞又会叫...

        那么开始模拟这款鸭子游戏吧!要求鸭子随着版本的不断更新,可能出现会游泳,会飞,会叫...等等不同功能。起初,很容易想到抽取基类鸭子,由具体鸭子负责实现功能,就形成了以下代码:
        恩,看起来不错,鸭子会叫会游,部分会飞的由子类自己去实现。但这样真的好吗?第二天,新的需求来了,再加入雕像鸭,野鸭以及玩具鸭,雕像鸭既不会叫,也不会游,更不会飞;野鸭会叫、会飞、会游;玩具鸭会游、会叫但不是“嘎嘎”。开始写具体的子类鸭子...
        最后我们发现因为没有某项功能的鸭子,为了避免从父类携带功能过来,都得保留空实现,例如:雕像鸭.
        
        随着鸭子的种类越来越多,功能也不断增加,那么对于不需要该功能的子类来说,必须以空实现的形式覆盖掉父类的功能,这样的设计可想有多糟糕。
        (1)或许你会说那么我们把这些方法都在父类中进行空实现吧,子类再根据实际功能覆写?——不得不说,这是一个多么糟糕的建议,继承的存在就是为了提高代码的重用性,如果使用空实现,父类还有何意义?
        (2)接口行吗?把功能写成接口,谁具备,谁实现?——是,这样貌似可以解决问题,但这样一来重复代码会越来越多,不是吗?
        
         现在我们知道,继承并不能很好地解决问题,因为鸭子的行为在子类中会不断改变,而让所有子类都具备这些行为又是不恰当的。接口的形式暂时是可以解决问题,但接口不具备实现功能,从而导致类似的功能代码重复。 那么,究竟该如何设计鸭子呢?
            
        设计原则:找到应用中可能需要变化的地方,把它们独立出来,不要和那些不需要变化的代码混在一起。
      
        怎么样的代码是需要变化的?——每当需求来了,都会使某部分代码做出修改,那么这部分代码需要被抽出来。
        想想?我们的鸭子哪些是再发生改变的?貌似所有的功能根据不同鸭子的特性都会有改变,那么抽出它们吧~       
        
            细细想想,飞行,叫,游等等功能随着鸭子的不同种类,实现也可能不一样(例如:野鸭“嘎嘎"叫,玩具鸭“吱吱”叫),也就是说每一个功能都会具有不同的实现,那么单独的功能又该如何设计?

        设计原则:面向接口编程,不要面向实现编程。
         
        无论如何实现call或者flay终归他们都是游和飞的动作,对于共性的东西我们要习惯向上归类,我们将所有的功能,以接口的形式形成规范,再有具体的行为进行实现,最后根据鸭子的不同种类,匹配自己的应有的功能即可。

          开始设计吧!(以Call进行举例)
           
            基于Call接口的三种实现:不会叫,嘎嘎叫,吱吱叫
        
        
        
        
        叫声接口以及具体实现都有了,剩下的就是与鸭子进行匹配了,我们开始修改BaseDuck.
        

        那么,在测试之前,我们还没有具体的鸭子类,以下就以玩具鸭为例。
        
       
        好,最后看看这样设计后的效果吧!
         

        运行结果:

        
        
         费了这么大劲,又是继承,又是接口的,总算是搞完了,那么这样做值得吗?回头看看我们都做了写什么,貌似如你所愿,你想要的一切皆有:鸭子继承于BaseDuck基类,飞行,叫等行为都以接口的形式提供标准,具体的行为都相互独立,对于共同行为的鸭子可以同用一份行为代码,从而减少代码的重复,更出乎意料的是我们的鸭子与行为是如此的默契,并且我们将编译时的工作同时扩展到了运行时,通过setter方法随时可以改变鸭子的行为,比起之前代码更据有弹性。
          
         书中《Head First 设计模式》提到一个概念,很好的解释了这种弹性思想的好处:“有一个"可能比“是一个”更好。之前的代码设计中我们将实现各种不同鸭子视为一个整体,它是一只什么什么鸭子;然而现在将思考提升到上一层,所有鸭子只是鸭子,它们都有Call、Swim、Fly等行为,只是表现形式不一样,将鸭子与行为独立起来,进行组装,形成新的类型,这就是”组合”。
            
         其实这也是一条需要我们去学习的 设计原则 多用组合,少用继承。

         如你所见,使用组合可以使我们的代码更具有弹性,不仅可将行为(算法)封装,更可以在运行时动态的改变行为(算法),只要它们遵循共同的接口标准即可。

         不是讲策略设计模式吗,绕了半天怎么一直再说鸭子?好吧,进入主题:策略设计模式。
         ...
         恭喜你,你已经学会这个模式了: 将算法进行封装,让它们之间可以相互替换,此模式将算法的变化与使用它的客户相互独立起来

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值