装饰者模式
Posted youxin2012
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了装饰者模式相关的知识,希望对你有一定的参考价值。
通过对已有类的包装,使新类在增加功能的同时,实现对已有类的复用。
装饰者模式 实现代码复用较 继承的优点:
- 在类之间没有明确的is-a关系的提前下 利用继承,后续代码维护较难。例 Duck extends Bird ,虽然Duck目前 完全可以复用 Bird中的方法eat, drink, 然而后期需要为Bird添加 fly() 方法时,Duck 就自然而然的继承了这个不该有的方法,so Duck被污染了。所以,切记不用为了一时的偷懒,强行利用继承复用非is-a的类
public class Bird
eat();
drink()
- 继承会在一定程度上 破坏类的封装性。子类依赖于 父类的实现细节
import java.util.Collection;
import java.util.HashSet;
public class InstrumentHashSet<E> extends HashSet<E>
private int addCount = 0;
public InstrumentHashSet()
public InstrumentHashSet(int initCap, float loadFactor)
super(initCap, loadFactor);
@Override
public boolean add(E e)
addCount++;
return super.add(e);
@Override
public boolean addAll(Collection<? extends E> c)
addCount += c.size();
return super.addAll(c);
public int getAddCount()
return addCount;
import java.util.Arrays;
public class HelloTest
public static void main(String[] args)
InstrumentHashSet<String> s = new InstrumentHashSet<String>();
s.addAll(Arrays.asList("the", "one", "two"));
System.out.println(s.getAddCount());
猜猜输出为多少
|
|
|
|
|
|
|
|
|
|
6
你以为super.addAll(c) 在实现有超类方法一次调用完成,然而实现 细节上 超类的addAll 通过调用 add来完成。
跟踪一下代码:
(InstrumentHashSet) addAll —> AbstractCollection addAll
public boolean addAll(Collection<? extends E> c)
boolean modified = false;
for (E e : c)
if (add(e)) // 此处3次调用 实现类InstrumentHashSet 的 add
modified = true;
return modified;
从而addCount 在addAll 中+3 一次,在add中 +1 三次,所以为6.
由于继承依赖于细节,所以我们需要对超类的实现细节有一定认识才能避免错误。如下对比相对傻瓜一些的包装类实现(只需关心 原有类提供的接口与输出,不会关注实现细节)
import java.util.Collection;
import java.util.HashSet;
public class WrapperHashSet<E>
private HashSet<E> hashSet;
private int acount = 0;
public WrapperHashSet(HashSet<E> hashSet)
this.hashSet = hashSet;
public void add(E e)
acount++;
hashSet.add(e);
public void addAll(Collection<? extends E> list)
acount += list.size();
hashSet.addAll(list);
如上WrapperHashSet 在 实现add, addAll分别用hashSet来调用实现,自身并不参与细节实现。
以上是关于装饰者模式的主要内容,如果未能解决你的问题,请参考以下文章