转发类示例

Kev*_*ith 5 java effective-java

阅读Effective Java,我从Item 16: Favor composition over inheritance.

在下面InstrumentedSet,这本书显示我们可以跟踪元素被插入的次数(通过InstrumentedSet.addCount变量)。

要做到这一点,我们可以简单地附加到这个类对象的addCount,然后调用ForwardingSet.add(),它调用实际Set类的 实际实现add()

// Reusable forwarding class 
public class ForwardingSet<E> implements Set<E> {     
  private final Set<E> s;     
  public ForwardingSet(Set<E> s) { this.s = s; }     
  public void clear()               { s.clear();            }    
  public boolean contains(Object o) { return s.contains(o); }
...
}

// Wrapper class - uses composition in place of inheritance   
public class InstrumentedSet<E> extends ForwardingSet<E> {     
      private int addCount = 0;     
      public InstrumentedSet(Set<E> s) { super(s); } 
      @Override public boolean add(E e) {         
          addCount++;
          return super.add(e);
       }
       ...
    }
Run Code Online (Sandbox Code Playgroud)

我的理解是否正确,要使用这种模式/方法,Forwarding*类必须调用其所有父类的方法(在这种情况下Set)?

And*_*hev 7

是的,您是对的,ForwardingSet将所有调用委托/转发到支持集。

您可能想看看流行的 Guava 库中的工作示例:ForwardingMap

  • 从理论上讲,是的 - 可以,这会给 Java 8 之前的实现的“ForwardingSet”带来一些小麻烦。在现实场景中,将通过在“AbstractSet”中引入默认实现方法来添加新方法,但是这个“ForwardingSet”是一个例外,它实现了“Set”,因此它不会获取它们。然而,从 Java 8 开始,它将接收默认的接口方法,这些方法将被放入“Set”(即新的“spliterator”)中。因此,您的“ForwardingSet”将在 Java 8 中派生这些新方法。 (2认同)
  • 如果声明“ForwardingSet&lt;E&gt;”最终执行了“Set&lt;E&gt;”所做的所有操作,那么声明它还有什么意义呢?即为什么不声明一个带有 `Set&lt;E&gt;` 成员变量的 `InstrumentedSet&lt;E&gt;` 呢?我个人不认为仅仅为了扩展它而声明“ForwardingSet&lt;E&gt;”有什么意义。 (2认同)