装饰模式
一.定义
装饰模式(Decorator Pattern):Attach additional responsibilities to an objectdynamically keeping the same interface.Decorators provide a flexible alternativeto subclassing for extending functionality.(动态地给一个对象添加一些额外的职责。就增加功能来说,装饰模式相比生成子类更为灵活。)
二. 我的理解
通过让装饰者和被装饰者实现相同的接口,即在最顶层它们共同的抽象,所以被修饰后都可以以接口的形式返回(不变)。比如不管一本书被最后装饰成了什么样,它们都可以抽象为引用类型。
过程:将被装饰者以接口的类型传入装饰器,作为Private的引用,返回装饰器,也是以接口的形式返回,所以外界觉得它还是原来的那个(虽然它已经被装饰了)。
三.描述
通用类图:
①Component抽象构件
Component,具体被修饰的对象和修饰器都实现了这个接口,所以才可以互换。
public abstract class Component {
//抽象的方法
public abstract void operate();//被装饰者被装饰的方法
}
②ConcreteComponent 具体构件
ConcreteComponent是Component的实现,代表的是那个原本的,还没被修饰那个,它就是等待被修饰的那个。
public class ConcreteComponent extends Component {
//具体实现
@Override
public void operate() {
System.out.println("do Something");//没被装饰之前的样子
}
}
③Decorator抽象装饰角色
一般是一个抽象类,它同被修饰者一样,都实现了Component,里面可不一定有抽象的方法,但是在它的属性里必然有一个private变量指向Component抽象构件,才能把要修饰的component的方法调出来进行修饰。
public abstract class Decorator extends Component {
private Componentcomponent = null;
//通过构造函数传递被修饰者
public Decorator(Component _component){
this.component = _component;
}
//委托给被修饰者执行
@Override
public void operate() {
this.component.operate();
}
}
④ConcreteDecoratorA和ConcreteDecoratorB具体装饰角色
具体实现怎么装饰。
public classConcreteDecorator1 extends Decorator {
publicConcreteDecorator1(Component _component){
super(_component); //传入被装饰者
}
//定义自己的修饰方法
private voidmethod1(){
System.out.println("method1修饰");
}
//具体实现怎么装饰,现在是被装饰后的方法了
public voidoperate(){//通常装饰都会加一些功能
this.method1();
super.operate();
}
}
⑤client:
public classClient {
public static voidmain(String[] args) {
Componentcomponent = new ConcreteComponent();
//第一次修饰
component = new ConcreteDecorator1(component);
//第二次修饰
component = newConcreteDecorator2(component);
//修饰后运行
component.operate();
}
}
五.优缺点
1.优点
①装饰类和被装饰类各自独立,独立扩展;
②装饰模式是对继承的有力补充,不管修饰多少层,返回的还是Component。
③动态地扩展一个实现类的功能。
2.缺点
①最好不要装饰太多层,不然出现问题不好确定是哪里出的。
四.经验
①想增加或扩展功能时,继承往往缺乏灵活性,因为不能多继承,而修饰可以不断的修饰;
②为一大批兄弟类扩展功能时,考虑装饰模式。
③当不时要修改下功能,即需要动态时,考虑修饰模式,能够多层装饰。
七.实际案例(非常有用!!!)
Java中的IO是明显的装饰器模式的运用。FilterInputStream,FilterOutputStream,FilterRead,FilterWriter分别为具体装饰器的父类,相当于Decorator类,它们分别实现了InputStream,OutputStream,Reader,Writer类(这些类相当于Component,是其他组件类的父类,也是Decorator类的父类)。继承自InputStream,OutputStream,Reader,Writer这四个类的其他类是具体的组件类,每个都有相应的功能,相当于ConcreteComponent类。而继承自FilterInputStream,FilterOutputStream,FilterRead,FilterWriter这四个类的其他类就是具体的装饰器对象类,即ConcreteDecorator类。通过这些装饰器类,可以给我们提供更加具体的有用的功能。如FileInputStream是InputStream的一个子类,从文件中读取数据流,BufferedInputStream是继承自FilterInputStream的具体的装饰器类,该类提供一个内存的缓冲区类保存输入流中的数据(扩展的功能)。我们使用如下的代码来使用BufferedInputStream装饰FileInputStream,就可以提供一个内存缓冲区来保存从文件中读取的输入流。