一、定义
定义:在不改变原有对象的基础上,将功能附加到对象上
提供了比继承更有弹性的替代方案(扩展原有对象功能)
类型: 结构型
二、使用场景
扩展一个类的功能或者给一个类添加附件职责
动态给一个对象添加功能,这些功能可以再动态的撤销
三、优点
继承的有力补充,比继承灵活,不改变原有对象的情况下给对象一个扩展功能
通过使用不同装饰类以及这些装饰类的排列组合,可以实现不同的效果
符合开闭原则
四、缺点
会出现更多的代码,更多的类,增加程序的复杂性
动态装饰时,多层装饰时会更复杂
五、相关设计模式
1. 装饰者模式和代理模式
装饰者模式关注一个对象动态添加方法
代理模式关注控制对对象的访问
六、Coding
1. 创建BatterCake 类
/**
* 煎饼
*/
public class BatterCake {
protected String getDesc(){
return "煎饼";
}
protected int cost(){
return 8;
}
}
2. 创建BatterCakeWithEgg
public class BatterCakeWithEgg extends BatterCake{
@Override
public String getDesc() {
return super.getDesc() + " 加一个鸡蛋";
}
@Override
public int cost() {
return super.cost() + 1;
}
}
3. 创建BatterCakeWithEggSausage类
public class BatterCakeWithEggSausage extends BatterCakeWithEgg{
@Override
public String getDesc() {
return super.getDesc() + " 加一根香肠";
}
@Override
public int cost() {
return super.cost() + 2;
}
}
4. 测试类
public class Test {
public static void main(String[] args) {
BatterCake batterCake = new BatterCake();
System.out.println(batterCake.getDesc() + " 销售价格:" + batterCake.cost());
BatterCakeWithEgg batterCakeWithEgg = new BatterCakeWithEgg();
System.out.println(batterCakeWithEgg.getDesc() + " 销售价格:" + batterCakeWithEgg.cost());
BatterCakeWithEggSausage batterCakeWithEggSausage = new BatterCakeWithEggSausage();
System.out.println(batterCakeWithEggSausage.getDesc() + " 销售价格:" + batterCakeWithEggSausage.cost());
}
}
缺点:不能增加个数,如需要两个鸡蛋和两个火腿肠
七、Coding(改进版本)
1. 创建ABatterCake抽象类
public abstract class ABatterCake {
protected abstract String getDesc();
protected abstract int cost();
}
2. 创建BatterCake类
public class BatterCake extends ABatterCake{
@Override
protected String getDesc() {
return "煎饼";
}
@Override
protected int cost() {
return 8;
}
}
3. 创建AbstractDecorator。 这里可以不用抽象类
public abstract class AbstractDecorator extends ABatterCake {
private ABatterCake aBatterCake;
public AbstractDecorator(ABatterCake aBatterCake){
this.aBatterCake = aBatterCake;
}
protected abstract void doSomething();
@Override
protected String getDesc() {
return this.aBatterCake.getDesc();
}
@Override
protected int cost() {
return this.aBatterCake.cost();
}
}
4. 创建装饰类 EggDecorator
public class EggDecorator extends AbstractDecorator{
public EggDecorator(ABatterCake aBatterCake) {
super(aBatterCake);
}
@Override
protected void doSomething() {
}
@Override
protected String getDesc() {
return super.getDesc() + " 加一个鸡蛋";
}
@Override
protected int cost() {
return super.cost() + 1;
}
}
5. 创建装饰类
public class SausageDecorator extends AbstractDecorator{
public SausageDecorator(ABatterCake aBatterCake) {
super(aBatterCake);
}
@Override
protected void doSomething() {
}
@Override
protected String getDesc() {
return super.getDesc() + "加一根香肠";
}
@Override
protected int cost() {
return super.cost() + 2;
}
}
6. 创建测试类
public class Test {
public static void main(String[] args) {
ABatterCake aBatterCake = new BatterCake();
aBatterCake = new EggDecorator(aBatterCake);
aBatterCake = new EggDecorator(aBatterCake);
aBatterCake = new EggDecorator(aBatterCake);
System.out.println(aBatterCake.getDesc() + " 销售价格:" + aBatterCake.cost());
}
}
7. UML图

八、装饰者模式在源码中的应用
1.java.io包下的BufferedReader类
继承于Reader抽象类。BufferedReader的构造器如下
public BufferedReader(Reader var1, int var2) {
super(var1);
this.markedChar = -1;
this.readAheadLimit = 0;
this.skipLF = false;
this.markedSkipLF = false;
if(var2 <= 0) {
throw new IllegalArgumentException("Buffer size <= 0");
} else {
this.in = var1;
this.cb = new char[var2];
this.nextChar = this.nChars = 0;
}
}
2. BufferedOutputStream和BufferedInputStream
BufferedOutputStream继承自FilterOutputStream, FilterOutputStream继承自OutputStream
BufferedOutputStream的构造器
public BufferedOutputStream(OutputStream var1, int var2) {
super(var1);
if(var2 <= 0) {
throw new IllegalArgumentException("Buffer size <= 0");
} else {
this.buf = new byte[var2];
}
}
3. FilterInputStream是一个装饰者,LineInputStream,BufferedInputStream,DataInputStream是实际的装饰者。

4. 在spring中的TransactionAwareCacheDecorator类
public class TransactionAwareCacheDecorator implements Cache {
private final Cache targetCache;
public TransactionAwareCacheDecorator(Cache targetCache) {
Assert.notNull(targetCache, "Target Cache must not be null");
this.targetCache = targetCache;
}
}
5. Mybatis中的org.apache.ibatis.cache.Cache类

例如FifoCache 类
public class FifoCache implements Cache {
private final Cache delegate;
private Deque<Object> keyList;
private int size;
public FifoCache(Cache delegate) {
this.delegate = delegate;
this.keyList = new LinkedList();
this.size = 1024;
}
}