装饰器模式(Decorator Pattern)属于结构型模式。用户向一个现有的对象添加新的功能,同时又不改变其结构。
例如,现在有个Girl类,学习的是语数外。现在有的女孩也有学习其他特长,在不改变Girl类的情况下,添加学习舞蹈、唱歌、绘画等特长。
Child抽象类:
public abstract class Child {
abstract void learn();
}
Girl类:
public class Girl extends Child{
@Override
public void learn() {
System.out.println("学习语数外");
}
}
Hobby为装饰抽象类,他需要继承Child类,并且持有child实例的引用:
public abstract class Hobby extends Child {
private Child child;
public Hobby(Child child) {
this.child = child;
}
@Override
void learn() {
child.learn();
}
}
具体的装饰类,唱歌、绘画、跳舞
public class Sing extends Hobby {
public Sing(Child child) {
super(child);
}
@Override
void learn() {
super.learn();
System.out.println("学会了唱歌");
}
}
public class Paint extends Hobby {
public Paint(Child child) {
super(child);
}
@Override
void learn() {
super.learn();
System.out.println("学会了绘画");
}
}
public class Dance extends Hobby {
public Dance(Child child) {
super(child);
}
@Override
void learn() {
super.learn();
System.out.println("学会了跳舞");
}
}
调用:
// 小花学习
Girl xiaoHua = new Girl();
xiaoHua.learn();
// 小丽除了学习,还学了绘画唱歌跳舞
Child xiaoLi = new Dance(new Sing(new Paint(girl)));
xiaoLi.learn();
输出结果:
学习语数外
学习语数外
学会了绘画
学会了唱歌
学会了跳舞
优点:装饰者模式比使用继承灵活一点。可以动态扩展一个对象的功能,在运行时选择不同的装饰器,从而实现不同的行为。具体构件类与具体装饰类可以独立变化。在使用装饰者模式时进行组合,原有代码无须改变,符合“开闭原则”。
缺点:多层装饰比较复杂。