?装饰器模式类比生活中房屋装修的场景,可以在毛坯房的基础上加以各种装饰,使得房屋的居住属性增强。装饰器模式能够在运行期间,动态地为原始对象增加一些额外的功能,使其功能更为丰富。
?装饰模式 可以动态的为某些对象增加一些额外的职责,在某些程度上,装饰器模式类似于继承,但是比继承更加灵活,可以在不改变一个对象本身功能的基础上额外增加新行为。装饰模式是一种对象结构性的模式。
?在定义中,我们提到了继承,通过继承的方式,子类可以在父类的功能上做增加,但这是在编译期间,需要修改子类来完成的。装饰模式可以在运行期间动态的包装
原始对象,实现“装饰”的效果。
?装饰模式的实现需要以下4个角色。
装饰器
抽象类的子类,可以有多种实现,在被装饰对象的基础上添加新的特性,真正实现功能增强的装饰器组件。?在下面的代码案例中,我们假设装修公司提供给客户两种装修方案,分别是中式装修和欧式装修,对于装饰器模式需要的4个角色,我们实现如下:
// 组件接口
public interface Component {
// 表示装饰的行为接口方法
void fitment();
}
// 毛坯房屋 - 被装饰的对象
public class RoughHouse implements Component {
// 组件接口的实现方法
@Override
public void fitment() {
System.out.print("【原始的毛坯房屋】");
}
}
// 抽象的装饰器
public abstract class AbstractDecorator implements Component {
// 声明的被装饰的对象属性
protected Component component;
// 构造方法中注入被装饰对象的属性
public AbstractDecorator(Component component) {
this.component = component;
}
// 装修的方法
@Override
public void fitment() {
component.fitment();
}
}
// 具体的装饰实现类 - 中式装修风格
public class ChineseStyle extends AbstractDecorator {
// 构造方法的注入
public ChineseStyle(Component component) {
super(component);
}
// 功能增强的方法
@Override
public void fitment() {
System.out.print("【中式装修的吊顶");
super.fitment();
System.out.print("】");
}
}
// 具体的装饰实现类 - 欧式装修风格
public class EuropeanStyle extends AbstractDecorator {
// 构造器 - 装饰对象的注入
public EuropeanStyle(Component component) {
super(component);
}
// 具体的装修风格
@Override
public void fitment() {
System.out.print("【欧式装修的家电家具");
super.fitment();
System.out.print("】");
}
}
// 客户端
public class Client {
public static void main(String[] args) {
// 只是中式装修
Component chineseStyle = new ChineseStyle(new RoughHouse());
chineseStyle.fitment();
System.out.println("");
// 只是欧式装修
Component europeanStyle = new EuropeanStyle(new RoughHouse());
europeanStyle.fitment();
System.out.println("");
// 中式装修+欧式装修
Component component = new EuropeanStyle(new ChineseStyle(new RoughHouse()));
component.fitment();
System.out.println("");
}
}
?根据上述房屋装修的代码示例,我们来画一下UML类图,如下所示:
?装饰器模式在某些场景下,如果只有一个具体的被装饰对象,那么抽象的装饰类可以直接作为该具体构件类的子类。
?在Java类库中,最典型的装饰器模式使用就是Java IO中的输入流和输出流的设计,总体来说,装饰器模式的使用场景还是比较多的。
?最后,我们来总结一下装饰模式的优点: