一、基本概念
1.定义
装饰(Decorator)模式又叫做包装模式,其功能是动态地给一个对象添加一些额外的职责。就增加功能来说,装饰模式相比生成子类更为灵活,是继承关系的一个替换方案。
装饰模式可以在不创造更多子类的情况下,将对象的功能加以扩展。装饰模式把客户端的调用委派到被装饰类。装饰模式的关键在于这种扩展完全是透明的
装饰模式的应用在 java 的 I/O 流中最为显著。
2.适用环境
该模式的适用环境为:
(1)在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。
(2)处理那些可以撤消的职责。
(3)当不能采用生成子类的方法进行扩充时。一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。另一种情况可能是因为类定义被隐藏,或类定义不能用于生成子类。
3.角色
-
抽象构件角色(Component):通常是一个抽象类或者一个接口,定义了一系列方法,方法的实现可以由子类实现或者自己实现。通常不会直接使用该类,而是通过继承该类或者实现该接口来实现特定的功能。
-
具体构件角色(Concrete Component):是 Component 的子类,实现了对应的方法,它就是那个被装饰的类。
-
装饰角色(Decorator):是 Component 的子类,它是具体装饰角色共同实现的抽象类(也可以是接口),并且持有一个 Component 型的对象引用,它的主要作用就是把客户端的调用委派到被装饰类。
-
具体装饰角色(Concrete Decorator):它是具体的装饰类,是 Decorator 的子类,当然也是 Component 的子类。它主要就是定义具体的装饰功能
4.uml图解
二、代码实现
被修饰基类——IComponentOutput接口
public interface IComponentOutput {
void operator();
}
被修饰子类——Output类
public class Output implements IComponentOutput {
@Override
public void operator() {
System.out.println("输出字节流");
}
}
修饰基类——AbstractBuffer抽象类
public abstract class AbstractBuffer implements IComponentOutput {
//修饰类需要引入被修饰类的基类对象,非常重要!!!
private IComponentOutput output;
public AbstractBuffer(IComponentOutput output) {
this.output = output;
}
@Override
public void operator() {
output.operator();
}
}
修饰实现类——Buffer1类
public class Buffer1 extends AbstractBuffer {
public Buffer1(IComponentOutput output) {
super(output);
}
@Override
public void operator() {
super.operator();
this.b1();
}
void b1() {
System.out.println("附加1");
}
}
修饰实现类——Buffer2类
public class Buffer2 extends AbstractBuffer {
public Buffer2(IComponentOutput output) {
super(output);
}
@Override
public void operator() {
super.operator();
this.b2();
}
void b2() {
System.out.println("附加2");
}
}
修饰实现类——Buffer3类
public class Buffer3 extends AbstractBuffer {
public Buffer3(IComponentOutput output) {
super(output);
}
@Override
public void operator() {
super.operator();
this.b3();
}
void b3() {
System.out.println("附加3");
}
}
有三个修饰子类,用于额外添加不同的附加功能
测试类——Client类
public class Client {
public static void main(String[] args) {
IComponentOutput output = new Output();
output.operator();
System.out.println("===定制1===");
AbstractBuffer b1 = new Buffer1(output);
AbstractBuffer b2 = new Buffer2(b1);
b2.operator();
System.out.println("===定制2===");
AbstractBuffer b3 = new Buffer3(output);
b3.operator();
}
}
执行结果为:
输出字节流
===定制1===
输出字节流
附加1
附加2
===定制2===
输出字节流
附加3
补充说明:
注意定制1这种方式:
AbstractBuffer b1 = new Buffer1(output);
AbstractBuffer b2 = new Buffer2(b1);
第二次的子类的参数是上一个已经修饰过的对象
这里的方法调用是:
Buffer2.operator()->AbstractBuffer.operator()+b()2
->output对象.operator()+b2()->b1.operator()+b2
这里的output对象就起了传递的作用