zoukankan      html  css  js  c++  java
  • 组合与继承 区别

    在本书中,把UML中的关联关系和聚集关系统称为组合关系。组合与继承都是提高代码可重用性的手段。在设计对象模型时,可以按照语义来识别类之间的组合关系和继承关系。在有些情况下,采用组合关系或者继承关系能完成同样的任务,组合和继承存在着对应关系:组合中的整体类和继承中的子类对应,组合中的局部类和继承中的父类对应,参见表6-1。本章6.9节(小结)中的表6-2总结了组合与继承的优缺点。

     

    表6-1 组合与继承的对应关系

    组 合 关 系

    继 承 关 系

    局部类

    父类

    整体类

    子类

    从整体类到局部类的分解过程

    从子类到父类的抽象过程

    从局部类到整体类的组合过程

    从父类到子类的扩展过程

    值得注意的是,本章所说的整体类和局部类比UML的聚集关系中的整体类和局部类具有更广泛的含义。在本章中,如果在类A中包含类C类型的属性,那么就把类A称为整体类或者包装类,把类C称为局部类或者被包装类。

    组合关系的分解过程对应继承关系的抽象过程


    图6-11 具有相同行为的类A和类B

          下面的例子未涉及具体的业务领域,该例子分别用组合关系与继承关系来建立一个对象模型。如图6-11所示,类A和类B有相同方法method1()、method2()和method3(),此外类A和类B还分别拥有methodA()和methodB()方法。在method3()方法中访问method1()方法,在mehodA()和methodB()方法中都会访问method2()方法。以下是类A和类B的源程序。
     

    1. public class A{  
    2. private void method1(){System.out.println("method1");}  
    3. private void method2(){System.out.println("method2");}  
    4. public void method3(){method1();System.out.println("method3");}  
    5. public void methodA(){method2();System.out.println("methodA");}  
    6. }  
    7. public class B{  
    8. private void method1(){System.out.println("method1");}  
    9. private void method2(){System.out.println("method2");}  
    10. public void method3(){method1();System.out.println("method3");}  
    11. public void methodB(){method2();System.out.println("methodB");}  
    12. }  
     

    图6-12 从类A和类B中抽象出父类C

    1.使用继承关系

          在图6-12中,从类A和类B中抽象出父类C,它包含method1()、method2()和method3()方法。由于在类A和类B中都会访问method2()方法,因此把method2()方法声明为protected类型。

    1. public class C{  
    2. private void method1(){System.out.println("method1");}  
    3. protected void method2(){System.out.println("method2");}  
    4. public void method3(){method1();System.out.println("method3");}  
    5. }  
    6. public class A extends C{  
    7. public void methodA(){method2(); System.out.println("methodA");}  
    8. }  
    9. public class B extends C{  
    10. public void methodB(){method2(); System.out.println("methodB");}  
    11. }  

    2.使用组合关系

          在图6-13中,类A与类C,以及类B与类C之间为组合关系。在类A中定义了C类型的引用变量c,类A的method3()方法直接调用类C的method3()方法。类A对类C进行了封装,类A被称为包装类,同样,类B也是包装类。由于在类A和类B中都会访问private类型的method2()方法,因此不能把method2()方法放在类C中定义,因为如果这样做,就必须在类C中把method2()方法定义为public类型,而这彻底破坏了封装。以下是类C、类A和类B的源程序。

    1. public class C{  
    2. private void method1(){System.out.println("method1");}  
    3. public void method3(){method1();System.out.println("method3");}  
    4. }  
    5. public class A {  
    6. private C c;  
    7. public A(C c){this.c=c;}  
    8. private void method2(){System.out.println("method2");}  
    9. public void method3(){c.method3();}  
    10. public void methodA(){method2(); System.out.println("methodA");}  
    11. }  
    12. public class B {  
    13. private C c;  
    14. public B(C c){this.c=c;}  
    15. private void method2(){System.out.println("method2");}  
    16. public void method3(){c.method3();}  
    17. public void methodB(){method2(); System.out.println("methodB");}  
    18. }  

    图6-13 从类A与类B中分解出局部类C

     

          组合关系和继承关系相比,前者的最主要优势是不会破坏封装,当类A与类C之间为组合关系时,类C封装实现,仅向类A提供接口;而当类A与类C之间为继承关系时,类C会向类A暴露部分实现细节。在软件开发阶段,组合关系虽然不会比继承关系减少编码量,但是到了软件维护阶段,由于组合关系使系统具有较好的松耦合性,因此使得系统更加容易维护。

    组合关系的缺点是比继承关系要创建更多的对象。以下程序演示在两种关系下创建类A的实例并且调用其methodA()方法。

    1. //类A与类C为组合关系  
    2. C c=new C();  
    3. A a=new A(c);  
    4. a.methodA();  
    5. // 类A与类C为继承关系  
    6. A a=new A();  
    7. a.methodA();  

          从以上程序看出,对于组合关系,创建整体类的实例时,必须创建其所有局部类的实例;而对于继承关系,创建子类的实例时,无须创建父类的实例。继承关系最大的弱点是打破了封装,子类能够访问父类的实现细节,子类与父类之间紧密耦合,子类缺乏独立性,从而影响了子类的可维护性。为了尽可能地克服继承的这一缺陷,应该遵循以下原则:

    ·精心设计专门用于被继承的类,继承树的抽象层应该比较稳定。

    ·对于父类中不允许覆盖的方法,采用final修饰符来禁止其被子类覆盖。

    ·对于不是专门用于被继承的类,禁止其被继承。

    ·优先考虑用组合关系来提高代码的可重用性。

    本章对组合关系和继承关系进行了比较,表6-2对这两种关系的优缺点做了总结。

     

    表6-2 比较组合关系与继承关系

    组 合 关 系

    继 承 关 系

    优点:不破坏封装,整体类与局部类之间松耦合,彼此相对独立

    缺点:破坏封装,子类与父类之间紧密耦合,子类依赖于父类的实现,子类缺乏独立性

    优点:具有较好的可扩展性

    缺点:支持扩展,但是往往以增加系统结构的复杂度为代价

    优点:支持动态组合。在运行时,整体对象可以选择不同类型的局部对象

    缺点:不支持动态继承。在运行时,子类无法选择不同的父类

    优点:整体类可以对局部类进行包装,封装局部类的接口,提供新的接口

    缺点:子类不能改变父类的接口

    缺点:整体类不能自动获得和局部类同样的接口

    优点:子类能自动继承父类的接口

    缺点:创建整体类的对象时,需要创建所有局部类的对象

    优点:创建子类的对象时,无须创建父类的对象

  • 相关阅读:
    GOF23设计模式之建造者模式
    GOF23设计模式之工厂模式
    GOF23设计模式之单例模式
    服务端字节流输出图片
    小记常见的会话跟踪技术
    Java生成随机数的三种方式
    因为new Date(),我给IE跪了
    ionic初体验
    cordova开发环境搭建
    gradle环境搭建
  • 原文地址:https://www.cnblogs.com/xflash/p/3771644.html
Copyright © 2011-2022 走看看