复合与继承的对比,装饰模式的实现
需要为现有的类增加额外的功能,比如为HashSet添加一个计数器,用于统计曾经添加到元素个数。
1. 继承方式
import java.util.Collection;import java.util.HashSet;/** * 带计数功能HashSet * 通过继承现有的HashSet,重写add(),addAll()方法,方法体中对addCount累计。 * 该实现方式是反面教材,因为使用继承而不是复合,而继承的方式由于子类并不知晓父类的实现方式而破坏了封装性。 * 事实上HashSet的addAll方法依赖于add方法,所覆盖的addAll最终还会调用add方法,使得计数器被重复累加,与预期不符。 * * @author JiaJia * * @param <E> */public class InstrumentedSetOne<E> extends HashSet<E> {/** * */private static final long serialVersionUID = 7144043784199771458L;private int addCount = 0;public InstrumentedSetOne() {}public InstrumentedSetOne(int initCap, float loadFactor) {super(initCap, loadFactor);}@Overridepublic boolean add(E o) {addCount++;return super.add(o);}@Overridepublic boolean addAll(Collection<? extends E> c) {addCount++;return super.addAll(c);}public int getAddCount() {return addCount;}}import java.util.Collection;import java.util.Set;/** * 带计数功能HashSet(复合,装饰模式实现) * 继承可重用的转发类ForwardingSet,添加了计数功能。 * 使用方法:Set<E> s = new InstrumentedSetTwo<E>(new HashSet<E>()); * 而且可以应用于所以扩展Set接口的类,比如: * Set<E> s2 = new InstrumentedSetTwo<E>(new TreeSet<E>()); * 该实现类被称为包装类,对Set接口进行了修饰,增加了特有功能。 * * @author JiaJia * * @param <E> */public class InstrumentedSetTwo<E> extends ForwardingSet<E> {private int addCount = 0;public InstrumentedSetTwo(Set<E> s) {super(s);}@Overridepublic boolean add(E o) {addCount++;return super.add(o);}@Overridepublic boolean addAll(Collection<? extends E> c) {addCount++;return super.addAll(c);}public int getAddCount() {return addCount;}}import java.util.Collection;import java.util.Iterator;import java.util.Set;/** * 复合实现的一部分:可重用的转发类 * 把需要复合的类声明为类变量,这里使用了接口Set,并扩展了接口Set,转发方法列表与需要复合的类一一对应。 * 同时把需要复合的类作为构造函数的参数(装饰模式)。 * * @author JiaJia * * @param <E> */public class ForwardingSet<E> implements Set<E> {private final Set<E> s;public ForwardingSet(Set<E> s) {this.s = s;}public boolean add(E o) {return s.add(o);}public boolean addAll(Collection<? extends E> c) {return s.addAll(c);}public void clear() {s.clear();}public boolean contains(Object o) {return s.contains(o);}public boolean containsAll(Collection<?> c) {return s.containsAll(c);}public boolean isEmpty() {return s.isEmpty();}public Iterator<E> iterator() {return s.iterator();}public boolean remove(Object o) {return s.remove(o);}public boolean removeAll(Collection<?> c) {return s.removeAll(c);}public boolean retainAll(Collection<?> c) {return s.retainAll(c);}public int size() {return s.size();}public Object[] toArray() {return s.toArray();}public <T> T[] toArray(T[] a) {return s.toArray(a);}@Overridepublic boolean equals(Object o) {return s.equals(o);}@Overridepublic int hashCode() {return s.hashCode();}@Overridepublic String toString() {return s.toString();}}