阅读Effective Java,我在Item 16: Favor composition over inheritance
看到了以下示例。
在下面的InstrumentedSet
中,本书显示我们可以跟踪元素的插入次数(通过InstrumentedSet.addCount
变量)。
为此,我们只需附加到此类对象的addCount
,然后调用ForwardingSet.add()
,它会调用实际的Set
类add()
的实际实现。< / p>
// 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);
}
...
}
我理解为了使用这种模式/方法,Forwarding*
类必须调用其父类的方法的全部(在这种情况下{{1} })?
答案 0 :(得分:3)
是的,你是对的,ForwardingSet
委托/转发所有对支持集的调用。
您可能希望查看热门库Guava中的工作示例:ForwardingMap。
答案 1 :(得分:0)
[没有足够的代表发表评论,所以我会留下答案]
回答您的问题:
<块引用>我的理解是否正确,要使用这种模式/方法,Forwarding* 类必须调用其所有父类的方法(在本例中为 Set)?
是的 - 这是实现装饰器模式的一种方式(如书中所述)。由于 Forwarding* 类实现了一个接口(即 Set<E>
接口),因此它必须遵守接口契约并实现这些方法。
对于您在评论中的问题:
<块引用>声明一个 ForwardingSet 有什么意义,如果它最终完成 Set 所做的一切? IE。为什么不用 Set 成员变量来声明一个 InstrumentedSet?
这样做可以让您有选择地修改要装饰的方法,从而删除大量样板代码。另外,当界面更新时,你只需要更新一个地方而不是N个地方(如果你有N个装饰器)。代码也更简洁易读,因为我不必在装饰器对象中实现每个方法。
举个例子...
下面我有转发类和 2 个装饰器 - 两者都只在向集合添加内容时修改行为,而没有其他内容..
如果设置界面发生变化,我现在只需要更新一个类 - ForwardingSet
类。如果我没有上那门课并按照你的建议去做,那么我会
需要在我的每个装饰器中实现整个 Set 接口(可读性不是很好)
我需要单独更新每个装饰器以实现更改(即新方法)
public abstract class ForwardingSet<E> implements Set<E> {
Set<E> delegate;
// set method delegations ...
}
/**
* in this decorator I want to log every time something is inserted (and ONLY
* inserted)
*/
public class LoggingSet<E> extends ForwardingSet<E> {
// constructor to set delegate
@Override
public void add(E e) {
log.info("Adding object to set...")
super.add(e);
}
}
/**
* in this decorator I increment a counter just like the example - again ONLY when
* inserting
*/
public class CountingSet<E> extends ForwardingSet<E> {
int count = 0;
// constructor to set delegate
@Override
public void add(E e) {
count++;
super.add(e);
}
}