模式定义:
在不改变原来类文件和使用继承的情况下,动态扩展一些功能。通过一个包装对象来包裹真实的对象。
注意点:(1)装饰对象和真实对象具备相同的接口。客户可以像与真实对象的交互一样来与包装对象交互。
(2)装饰对象包含一个真实对象的引用。
(3)包装对象接收来自客户的请求,并将之转发给真实对象。
(4)包装对象在转发这些请求的时候,附加一些功能。
遵循原则:
面向抽象编程,而不是面向实现编程;
优先使用对象组合而不是继承;
开闭原则;
封装变化部分。
适用场合:
(1)当我们需要动态地为对象增加功能;
(2)当对象的功能经常发生变化或者经常需要动态地增加功能时,避免为了适应这样的而变化而造成的类膨胀。
知识扩展:
JDK中的BufferedReader、BufferedWriter就是完美的实践者。
模式中的角色:
(1)被装饰者抽象【IBread】,是一个抽象类或者接口,是最基本的、原始的被装饰的对象。
(2)被装饰者具体实现类【NormalBread】,可以使一般实现类,也可以是装饰后的类。
(3)装饰者【AbstractBread】,一般是一个抽象类,里面必然含有被装饰者的引用。
(4)装饰者实现类【CornDecorator、SweetDecorator】,实现装饰效果。
烘烤面包的几个步骤
public interface IBread {
public void prepare();}
public class NormalBread implements IBread {
@Override
public void kneadFlour() {
System.out.println("和面");
}
@Override
public void prepare() {
System.out.println("准备蒸馒头");
}
@Override
public void stream() {
System.out.println("开始蒸");
}
@Override
public void process() {
this.prepare();
this.kneadFlour();
this.stream();
}
}
装饰者增强功能
public class CornDecorator extends AbstractBread {
public CornDecorator(IBread bread) {
super(bread);
}
public void paint(){
System.out.println("黑心的商贩开始染色");
}
@Override
public void kneadFlour() {
//和面之前染色
this.paint();
super.kneadFlour();
}
}
public class SweetDecorator extends AbstractBread {
public SweetDecorator(IBread bread) {
super(bread);
}
public void paint(){
System.out.println("黑心的商贩开始加入甜蜜素");
}
@Override
public void kneadFlour() {
this.paint();
super.kneadFlour();
}
}
测试
public class Client {
public static void main(String[] args) {
IBread normalBread = new NormalBread();
new SweetDecorator(new CornDecorator(normalBread)).process();
}
}