一.装饰器模式介绍
装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装。
这种模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能。
- 解决什么问题:为了扩展一个类的功能,经常会使用继承的方式实现,由于继承为类引入静态特征,并且随着扩展功能的增多,子类会很膨胀
- 什么情况下使用:在不想增加很多子类,把子类变得膨胀的前提下扩展类
- 如何解决:“组合”的思想
二.装饰者模式结构和实现
1.类图:
2.代码和解释:
Component是上层的一个抽象的接口,他提供一种公共的方法sampleOperation()
//.Component : 定义一个对象接口,可以给这些对象动态地添加职责。
interface Component {
public void operation();
}
// ConcreteComponent : 实现 Component 定义的接口。
class ConcreteComponent implements Component {
@Override
public void operation() {
System.out.println("初始行为");
}
}
Decorator : 装饰抽象类,继承了 Component, 从外类来扩展 Component 类的功能
class Decorator implements Component {
// 维护一个 Component 对象,和 Component 形成聚合关系
protected Component component;
// 传入要进一步修饰的对象
public Decorator(Component component) {
this.component = component;
}
@Override
// 调用要修饰对象的原方法
public void operation() {
component.operation();
}
}
ConcreteDecorator : 具体的装饰对象,起到给 Component对象 添加职责的功能。
class ConcreteDecoratorA extends Decorator {
private String addedState = "newState";
public ConcreteDecoratorA(Component component) {
super(component);
}
//对原方法进行了增强
public void operation() {
super.operation();
System.out.println("add state: " + addedState);
}
}
三.装饰者模式的应用 ----Java IO技术
1.IO体系
IO流用来处理设备之间的数据传输,Java程序中,对于数据的输入/输出操作 都是以“流”的方式进行的。java.io包下提供了各种“流”类的接口,用以获取不同种类的数据,并通过标准的方法输入或输出数据。
2.装饰器模式是如何应用的?
InputStream就是装饰者模式中的超类(Component)
注意,装饰者模式的超类并不一定是一个接口,因为接口和抽象类都有抽象的含义,个人认为要根据具体情况判断,代表“某种基础功能”的那个类或者接口就是Component.
package java.io;
//这里的InputStream就不是接口而是抽象类 它代表了输出流这种基本功能的组件
public abstract class InputStream implements Closeable {}
ByteArrayInputStream,FileInputStream相当于被装饰者(ConcreteComponent),他们都是对超类的直接继承,这些类都提供了最基本的字节读取功能。
FilterInputStream即是装饰者(Decorator),也是装饰类的基类,BufferedInputStream,DataInputStream,PushbackInputStream(都继承了FilterInputStream类)…这些都是被装饰者装饰后形成的成品,他们的目的是为了扩展FilterInputStream的功能。
public
class FilterInputStream extends InputStream {
/**
* The input stream to be filtered.
*/
protected volatile InputStream in;
可以看到 FilterInputStream作为装饰者,继承了超类InputStream的同时,其内部维护了一个InputStream,这样就可以通过构造器方法传入InputStream对象然后对其进行功能扩展了。
public BufferedInputStream(InputStream in, int size) {
super(in);
if (size <= 0) {
throw new IllegalArgumentException("Buffer size <= 0");
}
buf = new byte[size];
}
这是BufferedInputStream,这个类就继承了FilterInputStream,调用其父类构造器同时,添加了缓冲区的新功能。
四.优缺点
优点:装饰类和被装饰类可以独立发展,不会相互耦合,装饰模式是继承的一个替代模式,装饰模式可以动态扩展一个实现类的功能。
缺点:多层装饰比较复杂