Replace Inheritance with Delegation (以委托取代继承)

某个子类只使用超类接口中的一部分,或是根本不须要继承而来的数据。在子类中新建一个字段用以保存超类;调整子类函数,令它改而委托超类;而后去掉二者之间的继承关系    java

                                           

动机函数

继承是个好东西,但有时候它并非你要的。你经常会遇到这样的状况:一开始继承了一个类,随后发现超类中的许多操做并不真正适用于子类。这种状况下,你所拥有的接口并未真正反映出子类的功能。或者,你可能发现你从超类中继承了一大堆子类并不须要的数据,抑或你可能发现超类中的某些protected函数对子类并无什么意义。工具

你能够选择容忍,并接受传统说法:子类能够只使用超类功能的一部分。但这样作的结果是:代码传达的信息与你的意图南辕北辙这是一种混淆,你应该将它去除。测试

若是以委托取代继承,你能够更清楚地代表:你只须要受托类的一部分功能。接口中的哪一部分应该被使用,哪一部分应该被忽略,彻底由你主导控制。这样作的成本则是须要额外写出委托函数,但这些函数都很是简单,极少可能出错。this

作法 spa

 1.在子类中新建一个字段,使其引用超类的一个实例,并将它初始化为thiscode

2.修改子类内的全部函数,让它们再也不使用超类,转而使用上述那个受托字段。每次修改后,编译并测试。对象

注意:你不能这样修改子类中经过super调用超类函数的代码,不然它们会陷入无限递归。这种函数只有在继承关系被打破后才能修改。继承

3.去除两个类之间的继承关系,新建一个受托类的对象赋给受托字段。递归

4.针对客户端所用的每个超类函数,为它添加一个简单的委托函数

5.编译,测试。

范例:

   滥用继承的一个经典范例就是让Stack类继承Vector类---java 1.1的工具库(java.util)刚好就是这样作的。不过,做为范例,咱们只给出一个比较简单的形式:  

class MyStack extends Vector{
      public void push(Object element){
          insertElementAt(element,0);
      }
      
      public Object pop(){
         Object result = firstElement();
         removeElementAt(0);
         return result;
      }
}

,只要看看MyStack的用户,咱们就会发现,用户只要它作4件事:push(), pop(),sieze(), 和isEmpty()。后两个函数式从vector继承来的。

把这里的继承关系改成委托关系。首先,在MyStack中新建一个字段,用以保存受托的Vector对象。一开始,把这个字段初始化为this,这样在重构进行过程当中,就能够同时使用继承和委托:

private Vector _vector = this;

如今,开始修改MyStack的函数,让它们使用委托关系。首先从push()开始:

public void push(Object element){
  _vector.insertElementAt(element,0);
}

此时,编译并测试,一切都将运转如常。如今轮到pop();

public Object pop(){
  Object result = _vector.firstElement();
  _vector.removeElementAt(0);
  return result;
}

修改完全部的子类函数后,咱们能够打破与超类之间的联系了:

class MyStack{
  private Vector _vector = new Vector();
}

而后,对于Stack客户端可能用到的每个Vector函数,都必须在MyStack中添加一个简单的委托函数:

public int size(){
     return _vector.size();
}

public boolean isEmpty(){
    return _vector.isEmpty();
}

如今,编译并测试。若是忘记加入某个委托函数,编译器会告诉咱们。

相关文章
相关标签/搜索