我正在经历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);
}
...
}
答案 0 :(得分:5)
ForwardingSet
是一个框架。如果您必须在内部编写与其他Set
一起工作的几个Set
,但要在“香草” Set
之上提供不同的功能,则最好编写通用的分开一次而不是几次。
有效Java 中的Joshua Bloch将其称为“组合”,尽管实际实现看起来更像decorator pattern。
Guava中有一个名为ForwardingSet
的类,可以轻松获得实际的实现。
如果将来我们最终拥有更多类似InstrumentedSet的类,那么它们是否会促进重用并防止冗余呢?除了基本行为之外,这些类还需要做一些事情?
是的
这只是对设计进行过时验证吗?
是的
还是我想念的其他东西?
不,您什么都不丢失。
答案 1 :(得分:4)
是为了促进重复使用并防止冗余吗?是的。
是对设计进行过时验证吗?是的。
还有其他我想念的东西吗?否。
“转发”通常称为“ 授权”。
参见:What is the purpose of a delegation pattern?
一些带有仅委托实现的Java类示例:
java.io.FilterInputStream
(和java.io.FilterOutputStream
,java.io.FilterReader
,java.io.FilterWriter
)
类
FilterInputStream
本身只是使用将所有请求传递到所包含的输入流的版本来简单地覆盖InputStream
的所有方法。FilterInputStream
的子类可以进一步覆盖其中的某些方法,还可以提供其他方法和字段。
javax.servlet.ServletRequestWrapper
(和javax.servlet.ServletResponseWrapper
,javax.servlet.http.HttpServletRequestWrapper
,javax.servlet.http.HttpServletResponseWrapper
)
为
ServletRequest
接口提供了一个方便的实现,希望开发者将请求调整为适合Servlet的开发人员可以将其子类化。此类实现包装器或装饰器模式。方法默认情况下是调用包装的请求对象。