概念和功能
装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构。这种还是属于结构型模式。它是作为现有的类的一个包装,这种模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能。
使用场景和方法
使用场景大抵是: 1、扩展一个类的功能。 2、动态增加功能,动态撤销。
相较于继承子类的解决方案来说主要解决的是——由于继承为类引入静态特征,并且随着扩展功能的增多,子类会很膨胀。在不想增加很多子类的情况下扩展类的功能。
使用方法大抵是:1、让适配器类继承某个类的对象实现需要的接口,修改指定方法。2、通过在适配器类中添加某个类的对象实现需要适配的接口。
优点:装饰类和被装饰类可以独立发展,不会相互耦合,装饰模式是继承的一个替代模式,装饰模式可以动态扩展一个实现类的功能。
缺点:多层装饰比较复杂。
实例分析
简单的实例:电源适配器——现在我想在不改变电源适配器类的结构下扩展一个功能——变色。
- 我可以新增一个类继承这个适配器类,然后新增一个方法setColor,这样的缺点是不灵活,我想再添加一个方法setShape,这种模式下去类之间的继承关系越来越复杂,子类越来越膨胀,还会出现如果我基类的属性值更改了,我的各个子类都可能受到影响。那可能会想到我用实现接口的方式啊,可还是会出现上述问题,接口和继承本就是很相像的。
- 那我能实现一个功能,但是这个功能的具体实现是和原来的类“分开”(松耦合)的,这个功能实现类只是接受原来类提供的一些参数而已。
方法一:
适配器的子类:
public class PowerAdapterSubClass<T extends ElectricApp> extends PowerAdapter{
//the Attribute(color) can be more appropriate in base struct
private int color = 0x00000000;
public PowerAdapterSubClass(ElectricApp app, PowerProvider provider) {
super(app, provider);
}
public void setColor(int colorARGB) {
//do something to change the color ......
color = colorARGB;
}
}
使用的方法很简单:
Phone phone = new Phone();
PowerProvider powerProvider = new PowerProvider();
//add function :setColor(color)
PowerAdapterSubClass powerAdapterSubClass = new PowerAdapterSubClass<Phone>(phone, powerProvider);
powerAdapterSubClass.setColor(0x00ffffff);
这里在使用的时候直接实例化PowerAdapter的子类powerAdapterSubClass,然后调用子类中新增的setColor方法就完成新增功能的调用了。
方法二:
适配器的装饰类:
public class PowerAdapterDecorator implements Power {
//the Attribute(color) can be more appropriate in base struct
private int color = 0x00000000;
private PowerAdapter powerAdapter;
public PowerAdapterDecorator(PowerAdapter adapter) {
this.powerAdapter = adapter;
}
public void setColor(int colorARGB) {
//do something to change the color ......
color = colorARGB;
}
@Override
public int powerOut() {
return this.powerAdapter.powerOut();
}
}
运行的时候就是这样了:
Phone phone = new Phone();
PowerProvider powerProvider = new PowerProvider();
PowerAdapter powerAdapter = new PowerAdapter<Phone>(phone, powerProvider);
//add function :setColor(color)
PowerAdapterDecorator powerAdapterDecorator = new PowerAdapterDecorator(powerAdapter);
powerAdapterDecorator.setColor(0x00ffffff);
phone.setPower(powerAdapterDecorator);
System.out.print("phone current volume is " + phone.charging());
适配器的在不继承的情况下想添加功能,最常用关键的方法是持有想扩展方法的原始类的实例。就是上面栗子中的PowerAdapterDecorator powerAdapterDecorator = new PowerAdapterDecorator(powerAdapter);这句。拿到了实例才能很好的扩展他的功能。这样装饰类PowerAdapterDecorator和原来的PowerAdapter分工明确、独立开发和扩展不会相互耦合,这也是装饰器模式的优点了。但说是独立开发互不影响也不是那么“理想”,装饰器模式设计之初就是辅助原始类更好的实现多变的功能的,所以装饰器模式方法基本都是辅助原始类方法或者属性的。比如上面例子中的changeColor就是用来辅助原始类中color属性的,这个changeColor功能可有可没有,只是需要提供了这个方法来动态改变color,创建了装饰器类来完成这个功能。同时还会有一个缺点,我需要实现多层装饰,后面的一层就需要有前一层的实例,设计功能的时候会很复杂,多层之间的是怎么明确分工的,所以建议最多只做一两层的“装饰”。
Android中装饰器模式的经典实现就是Context、ContextWrapper和ContextThemeWrapper等,等后面看了源码再来深度理解一下他们实现的装饰器模式。