定义
装饰器模式(Decorator Pattern),也称为包装模式(Wrapper Pattern)是指在不改变原有对象的基础之上,将功能附加到对象上,提供了比继承更有弹性的替代方案(扩展原有对象的功能),属于结构型模式。
应用场景
装饰器模式在我们生活中应用也比较多,如给煎饼加鸡蛋;给蛋糕加上一些水果;给房子装修等,为对象扩展一些额外的职责。装饰器在代码程序中适用于以下场景:
1、用于扩展一个类的功能或给一个类添加附加职责。
2、动态的给一个对象添加功能,这些功能可以再动态的撤销。
3、需要为一批的兄弟类进行改装或加装功能。
代码实现
public abstract class Battercake {
protected abstract String getMsg();
protected abstract int getPrice();
}
public class BaseBattercake extends Battercake{
@Override
protected String getMsg(){ return "煎饼";}
@Override
public int getPrice(){ return 5;}
}
public class BattercakeDecorator extends Battercake{
private Battercake battercake;
public BattercakeDecorator(Battercake battercake) {
this.battercake = battercake;
}
@Override
protected String getMsg(){ return this.battercake.getMsg();}
@Override
public int getPrice(){ return this.battercake.getPrice();}
}
public class EggDecorator extends BattercakeDecorator{
public EggDecorator(Battercake battercake) {
super(battercake);
}
@Override
protected String getMsg(){ return super.getMsg() + "1个鸡蛋";}
@Override
public int getPrice(){ return super.getPrice() + 1;}
}
public class SauageDecorator extends BattercakeDecorator{
public SauageDecorator(Battercake battercake) {
super(battercake);
}
@Override
protected String getMsg(){ return super.getMsg() + "1根香肠";}
@Override
public int getPrice(){ return super.getPrice() + 2;}
}
public class Test {
public static void main(String[] args) {
Battercake battercake;
battercake = new BaseBattercake();
battercake = new EggDecorator(battercake);
battercake = new SauageDecorator(battercake);
System.out.println(battercake.getMsg() + ",总价" + battercake.getPrice());
}
}
装饰器模式的核心是功能扩展,使用装饰器模式可以透明且动态地扩展类的功能。其实现原理为:让装饰器和被包装类(BaseBattercake)实现相同的接口(Battercake)(使得装饰器与被扩展类类型一致),并在构造函数中传入该接口(Battercake)对象,然后就可以在接口需要实现的方法中在被包装类对象的现有功能上添加新功能了。而且由于装饰器与被包装类属于同一类型(均为Battercake),且构造函数的参数为其实现接口类(Battercake),因此装饰器模式具备嵌套扩展功能,这样我们就能使用装饰器模式一层一层的对最底层被包装类进行功能扩展了。
在源码中的应用
装饰器模式在源码中也应用得非常多,在JDK中体现最明显的类就是IO相关的类,如BufferedReader、InputStream、OutputStream等,在Spring 中的TransactionAwareCacheDecorator类,MyBatis 中处理缓存的设计 org.apache.ibatis.cache.Cache类等等。
优缺点
优点:
1、装饰器是继承的有力补充,比继承灵活,不改变原有对象的情况下动态地给一个对象扩展功能,即插即用。
2、通过使用不同装饰类以及这些装饰类的排列组合,可以实现不同效果。
3、装饰器完全遵守开闭原则。
缺点:
1、会出现更多的代码,更多的类,增加程序复杂性。
2、动态装饰时,多层装饰时会更复杂。