1、角色
- Component: 抽象构件
- ConcreteComponent: 具体构件
- Decorator: 抽象装饰类
- ConcreteDecorator: 具体装饰类
2、UML类图
3、源码
public class DecoratorPatterns {
public static void main(String[] args) {
ProgramMonkey programMonkey = new JavaProgramMonkey();
programMonkey.program();
ProgramMonkey advancedProgramMonkey = new RealProgramMonkeyDecorator(new JavaProgramMonkey());
advancedProgramMonkey.program();
}
}
/**
* 抽象构件
*/
interface ProgramMonkey {
void program();
}
/**
* 具体构件
*/
class JavaProgramMonkey implements ProgramMonkey {
public void program() {
System.out.println("会编写Java程序");
}
}
/**
* 具体构件
*/
class WebFrontProgramMonkey implements ProgramMonkey {
public void program() {
System.out.println("会编写Web前端程序");
}
}
/**
* 抽象装饰者,通过组合的方式,调用原构件的方法
*/
abstract class ProgramMonkeyDecorator implements ProgramMonkey {
private ProgramMonkey programMonkey;
public ProgramMonkeyDecorator(ProgramMonkey programMonkey) {
this.programMonkey = programMonkey;
}
public void program() {
programMonkey.program();
}
}
/**
* 具体装饰者类,给原构件添加了新的方法
*/
class RealProgramMonkeyDecorator extends ProgramMonkeyDecorator {
public RealProgramMonkeyDecorator(ProgramMonkey programMonkey) {
super(programMonkey);
}
@Override
public void program() {
super.program();
System.out.println("会设计模式");
}
}
输出结果
会编写Java程序
会编写Java程序
会设计模式
具体的装饰者给原构件透明的添加了新的功能
4、优点
- 装饰模式与继承关系的目的都是要扩展对象的功能,但是装饰模式可以提供比继承更多的灵活性。
- 具体构件类与具体装饰类可以独立变化,用户可以根据需要增加新的具体构件类和具体装饰类,在使用时再对其进行组合,原有代码无须改变,符合“开闭原则”
5、缺点
- 这种比继承更加灵活机动的特性,也同时意味着装饰模式比继承更加易于出错,排错也很困难,对于多次装饰的对象,调试时寻找错误可能需要逐级排查,较为烦琐。
6、jdk中的体现
- BufferedInputStream 具体装饰者
- FilterInputStream 装饰者
- InputStream Compenent
- FileInputStream 具体的compenent
// 该类为Compenent类
public abstract class InputStream implements Closeable {
// Adaptee的read方法
public int read(byte b[], int off, int len) throws IOException {
...
}
}
// 该类为具体的Compenent类
public class FileInputStream extends InputStream {
public int read(byte b[], int off, int len) throws IOException {
return readBytes(b, off, len);
}
}
// 该类为装饰者类
public class FilterInputStream extends InputStream {
protected volatile InputStream in;
protected FilterInputStream(InputStream in) {
this.in = in;
}
public int read() throws IOException {
return in.read();
}
}
// 该类为具体的装饰者实现类
public class BufferedInputStream extends FilterInputStream {
public synchronized int read() throws IOException {
if (pos >= count) {
fill();
if (pos >= count)
return -1;
}
return getBufIfOpen()[pos++] & 0xff;
}
}