有效的Java项目16(第2版)-转发类是否仅用于允许重用?

lin*_*oob 3 java oop effective-java

我正在经历Effective Java, Item-16 Favor composition over inheritance。我看了Forwarding class下面的例子。

我想知道ForwardingSet上课有什么意义?InstrumentedSet可以很好地实现Set并拥有一个私有实例来调用所有方法。

如果InstrumentedSet将来我们最终拥有更多类似的类,这些类除了基本行为外还需要做一些事情,是否可以促进重用并防止冗余?仅仅是面向未来的设计还是我缺少的其他东西?

// 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)

Oli*_*ire 5

是的,ForwardingSet是一个框架。

如果必须在内部编写Set与其他Sets 一起工作的s,但要在“ vanilla”之上提供不同的功能,则Set最好只编写一次而不是几次。

Joshua Bloch在Effective Java中将其称为“组合”,尽管实际实现看起来更像装饰器模式

Guava中,可以使用名为的类轻松获得实际的实现ForwardingSet

如果将来我们最终拥有更多的InstrumentedSet之类的类,而这些类除了基本行为之外还需要做一些事情,是否可以促进重用并防止冗余?

是。

它只是面向未来的设计吗?

是。

还是我还缺少其他东西?

不,您什么都不丢失。

  • @linuxNoob如果要装饰的对象实现了许多方法,而您仅修改了一些方法(如果有的话)的行为,那么仅使用委托的基类可以将委托逻辑与装饰逻辑(即基数)分开。类仅进行委派,因此它实际上不需要进行测试和审查,而子类仅进行装饰,因此需要进行测试和审查。装饰逻辑将不会“淹没”在委托逻辑的海洋中。另请参阅:[关注点分离](https://en.wikipedia.org/wiki/Separation_of_concerns)。 (2认同)