zoukankan      html  css  js  c++  java
  • 多用组合,少用继承

      一般情况下,继承(主要是由类实现)可能比组合(主要是由接口实现)更好实现,而且继承似乎有种一劳永逸的牛叉功能。这篇随笔是我读过一篇文章之后的一些想法,欢迎各位指教讨论。

      一般情况下,我们总是花许多时间在系统的维护和变化上,有时会比开发花的时间更多,所以我们应该致力于提高可维护性和可扩展性上的复用程度,而继承在这方面可能略逊于组合,当然也有特殊情况。。。

      使用组合建立的系统具有很大的弹性,不仅可以将算法族封装成类,更可以在运行时动态地改变行为,只要组合的行为对象符合正确的接口标准即可。

      下面用一些代码来具体说说。。。还是用策略模式中的例子。

        public abstract class Cat
      {
        IEatBehavior pEatBehavior;   // 为行为接口定义一个引用变量
        public void Eat()
        {
          pEatBehavior.Eat(); 
        }
        public void Drink()
        {
          System.Out.Println(" I Drink Water.");
        }
      }
      public class WhiteCat Extends Cat
      {
        public WhiteCat()
        {
          pEatBehavior = new WhiteCatEatBehaviorClass();   // WhiteCatEatBehaviorClass 是实现接口 IEatBehavior 的一个具体类,
                                          // 里面的细节可以不用管,
                                         // 你只需要知道这是白猫特有的吃法就行了                              
        }
      } 

     

      现在白猫也有自己 不同于 超类中的喝,如果使用继承的话,只要覆盖超类中的方法Drink()即可,但想一想,如果有很多子类继承该超类呢,那就得一个一个的覆盖,这可是体力活了。。。所以觉得在这使用组合可能更合适一点,现在就干起来,首先来新建一个含有Drink()方法的接口和一些具体类 

        public interface IDrinkBehavior
      {
        public Drink();
      }
      public class WhiteCatDrinkBehavior implements IDrinkBehavior
      {
        public void Drink()
        {
          System.Out.Println(" I Drink Soup.");
        }
      }

     

      下面让我们再重新写一下超类及它的子类

        public abstract class Cat
      {
        IEatBehavior pEatBehavior;         // 为吃行为接口定义一个引用变量
        IDrinkBehavior pDrinkBehavior;     // 为喝行为接口定义一个引用变量,有了这个变量,原来的Drink()方法就可以简化了
        public void Eat()
        {
          pEatBehavior.Eat();
        }
        public void Drink()
        {
          pDrinkBehavior.Drink();       // 直接委托给 pDrinkBehavior 对象办就可以了
        }
      }
      public class WhiteCat Extends Cat
      {
        public WhiteCat()
        {
          pEatBehavior   = new WhiteCatEatBehaviorClass(); 
          pDrinkBehavior = new WhiteCatDrinkBehaviorClass();    // 实例化一下,指明 喝 这个行为委托给哪个具体类来执行
        }
      }

     

      上面提到了可以在运行时动态地改变行为,这里也介绍一下实现方法,我们可以在超类中,加入两个方法:

      

    public abstract class Cat
    {
        // 之前的方法,变量不变
        // 添加的方法
    
        public Void SetEatBehavior(IEatBehavior pNewEatBehavior)
        {
            pEatBehavior = pNewEatBehavior;
        }
    
        public Void SetDrinkBehavior(IDrinkBehavior pNewDrinkBehavior)
        {
            pDrinkBehavior = pNewDrinkBehavior;
        }
    }

     

      这样就可以在运行时调用SetEatBehavior,SetDrinkBehavior方法动态地改变行为了(组合的一大优点)。一般情况下,对象的 多种不同行为 适合 组合 来组织,而 静态的状态,类型等 适合 继承 来组织(这只是一家之说,仅参考)。。。

     

     

     

     

     

     

     

     

     

     

     

     

  • 相关阅读:
    存在主义危机
    噪声干扰
    Jupiter 2 Modem State Codes
    广域网优化协议欺骗
    RF / IF 信号
    意识清晰九度
    m3u8downloader
    JS禁用浏览器退格键
    Ruby on rails开发从头来(五十一) ActiveRecord基础(并发处理)
    来自Rails世界的项目管理工具Redmine
  • 原文地址:https://www.cnblogs.com/hachun/p/3456661.html
Copyright © 2011-2022 走看看