装饰器模式
动态地给对象添加一些额外的职责。就功能来说装饰模式相比生成子类更为灵活。
结构
- 抽象组件(Component):需要装饰的抽象对象。
- 具体组件(ConcreteComponent):是我们需要装饰的对象
- 抽象装饰类(Decorator):内含指向抽象组件的引用及装饰者共有的方法。
- 具体装饰类(ConcreteDecorator):被装饰的对象。
demo
Component.class
/**
* 组件对象的接口,可以给这些对象动态的添加职责
* @author yuyufeng
*/
public abstract class Component {
/**
* 示例方法
*/
public abstract void operation();
}
Decorator.class
/**
* 装饰器接口,维持一个指向组件对象的接口对象, 并定义一个与组件接口一致的接口
*
* @author Yu Yufeng
*
*/
public abstract class Decorator extends Component {
/**
* 持有组件对象
*/
protected Component component;
/**
* 构造方法,传入组件对象
*
* @param component
* 组件对象
*/
public Decorator(Component component) {
this.component = component;
}
@Override
public void operation() {
// 转发请求给组件对象,可以在转发前后执行一些附加动作
component.operation();
}
}
ConcreteComponent.class
/**
* 具体实现组件对象接口的对象
*
* @author Yu Yufeng
*
*/
public class ConcreteComponent extends Component {
@Override
public void operation() {
// 相应的功能处理
System.out.println("ConcreteComponent.operation()");
}
}
ConcreteDecoratorA.class
/**
* <p>
* 装饰器的具体实现对象,向组件对象添加职责,operationFirst(),operationLast()为前后需要添加的功能。
* 具体的装饰器类ConcreteDecoratorB代码相似,不在给出。
* </p>
*
* @author Yu Yufeng
*
*/
public class ConcreteDecoratorA extends Decorator {
public ConcreteDecoratorA(Component component) {
super(component);
}
// 在调用父类的operation方法之前需要执行的操作
private void operationFirst() {
System.out.println("ConcreteDecoratorA.operationFirst()");
}
// 在调用父类的operation方法之后需要执行的操作
private void operationLast() {
System.out.println("ConcreteDecoratorA.operationLast()");
}
// 调用父类的方法,可以在调用前后执行一些附加动作
@Override
public void operation() {
operationFirst(); // 添加的功能
super.operation(); // 这里可以选择性的调用父类的方法,如果不调用则相当于完全改写了方法,实现了新的功能
operationLast(); // 添加的功能
}
}
ConcreteDecoratorB.class
/**
* <p>
* 装饰器的具体实现对象,向组件对象添加职责,operationFirst(),operationLast()为前后需要添加的功能。
* 具体的装饰器类ConcreteDecoratorB代码相似,不在给出。
* </p>
*
* @author Yu Yufeng
*
*/
public class ConcreteDecoratorB extends Decorator {
public ConcreteDecoratorB(Component component) {
super(component);
}
// 在调用父类的operation方法之前需要执行的操作
private void operationFirst() {
System.out.println("ConcreteDecoratorB.operationFirst()");
}
// 在调用父类的operation方法之后需要执行的操作
private void operationLast() {
System.out.println("ConcreteDecoratorB.operationLast()");
}
// 调用父类的方法,可以在调用前后执行一些附加动作
@Override
public void operation() {
operationFirst(); // 添加的功能
super.operation(); // 这里可以选择性的调用父类的方法,如果不调用则相当于完全改写了方法,实现了新的功能
operationLast(); // 添加的功能
}
}
Test.class
/**
* 装饰器模式测试
*
* @author Yu Yufeng
*
*/
public class Test {
public static void main(String[] args) {
Component c1 = new ConcreteComponent(); // 首先创建需要被装饰的原始对象(即要被装饰的对象)
Decorator decoratorA = new ConcreteDecoratorA(c1); // 给对象透明的增加功能A并调用
decoratorA.operation();
Decorator decoratorB = new ConcreteDecoratorB(c1); // 给对象透明的增加功能B并调用
decoratorB.operation();
System.out.println("------------------------------------");
// 装饰器也可以装饰具体的装饰对象,此时相当于给对象在增加A的功能基础上再添加功能B
Decorator decoratorBandA = new ConcreteDecoratorB(decoratorA);
decoratorBandA.operation();
}
}
应用
java io中的 InputStream
示例
File file = new File("d://test/in.txt");
//建需要被装饰的原始对象
InputStream inputStream = new FileInputStream(file);
//给对象增加buffer功能
BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream, 1024);
byte[] bytes = new byte[10];
int read;
StringBuilder stringBuilder = new StringBuilder();
while ((read = bufferedInputStream.read(bytes)) != -1) {
stringBuilder.append(new String(bytes, 0, read));
}
System.out.println(stringBuilder);
组件对象的接口InputStream.class ,可以给这些对象动态的添加职责
public abstract class InputStream implements Closeable {
public abstract int read() throws IOException;
//...
}
装饰器接口 FilterInputStream.class ,维持一个指向组件对象的接口对象, 并定义一个与组件接口一致的接口
public
class FilterInputStream extends InputStream {
protected volatile InputStream in;
protected FilterInputStream(InputStream in) {
this.in = in;
}
public int read() throws IOException {
return in.read();
}
//...
}