装饰模式:动态地给一个对象添加一些额外的职责(以对客户端透明的方式扩展对象的功能),就增加功能来说,装饰模式相比生成子类更为灵活,是继承关系的一个替代方案。
装饰模式的四个角色:
- 抽象构件(Component)角色:给出一个抽象接口,以规范准备接收附加责任的对象。在装饰模式中,必然有一个最基本、最原始、最核心的接口或者抽象类充当Component抽象构件。
- 具体构件(ConcreteComponent)角色:定义一个将要接收附加责任的类。
- 装饰(Decorator)角色:持有一个构件(Component)对象的实例,并定义一个与抽象构件接口一致的接口。
- 具体装饰(ConcreteDecorator)角色:负责给构件对象“贴上”附加的责任。
1. 透明性的要求
装饰模式对客户端的透明性要求程序不要声明一个ConcreteComponent类型的变量,而应当声明一个Component类型的变量。
下面的做法是对的:
装饰模式对客户端的透明性要求程序不要声明一个ConcreteComponent类型的变量,而应当声明一个Component类型的变量。
下面的做法是对的:
Component component = new ConcreteComponent();
component = new ConcreteDecorator(component);
而下面的做法是不对的:
Component component = new ConcreteComponent();
ConcreteDecorator componentDecorator = new ConcreteDecorator(component);
2. 半透明的装饰模式
纯粹的装饰模式很难找到。装饰模式的用意是在不改变接口的前提下,增强所考虑的类的性能。在增强性能的时候,往往需要建立新的公开的方法,即在具体装饰(ConcreteDecorator)角色里增加一个newMethod()方法。这就导致了大多数的装饰模式的实现都是“半透明”的,而不是完全透明的。换言之,允许装饰模式改变接口,增加新的方法。这意味着客户端可以声明ConcreteDecorator类型的变量,从而可以调用ConcreteDecorator类中才有的方法:
Component component = new ConcreteComponent();
ConcreteDecorator componentDecorator = new ConcreteDecorator(component);
componentDecorator.newMethod();
半透明的装饰模式是介于装饰模式和适配器模式之间的。适配器模式的用意是改变所考虑的类的接口,也可以通过改写一个或几个方法,或增加新的方法来增强或改变所考虑的类的功能。大多数的装饰模式实际上是半透明的装饰模式,这样的装饰模式也称做半装饰、半适配器模式。3. 装饰模式的优点
- 装饰模式与继承关系的目的都是要扩展对象的功能,但是装饰模式可以提供比继承更多的灵活性。装饰模式允许系统动态决定“贴上”一个需要的“装饰”,或者除掉一个不需要的“装饰”。继承关系则不同,继承关系是静态的,它在系统运行前就决定了。
- 通过使用不同的具体装饰类以及这些装饰类的排列组合,设计师可以创造出很多不同行为的组合。
- 由于使用装饰模式,可以比使用继承关系需要较少数目的类。使用较少的类,当然使设计比较易于进行。但是,在另一方面,使用装饰模式会产生比使用继承关系更多的对象。更多的对象会使得查错变得困难,特别是这些对象看上去都很相像。
1. 模版代码
//抽象构件
public abstract class Component {//抽象的方法public abstract void operate();
}//具体构件
public class ConcreteComponent extends Component {//具体实现@Overridepublic void operate() {System.out.println("do Something");}}//抽象的装饰者类
public abstract class Decorator extends Component {private Component component = null;//通过构造函数传递被修饰者public Decorator(Component _component){this.component = _component;}//委托给被修饰者执行@Overridepublic void operate() {this.component.operate();}}//具体的装饰类1
public class ConcreteDecorator1 extends Decorator {//定义被修饰者public ConcreteDecorator1(Component _component){super(_component);}//定义自己的修饰方法private void method1(){System.out.println("method1 修饰");}//重写父类的Operation方法public void operate(){this.method1();super.operate();}
}//具体的装饰类2
public class ConcreteDecorator2 extends Decorator {//定义被修饰者public ConcreteDecorator2(Component _component){super(_component);}//定义自己的修饰方法private void method2(){System.out.println("method2修饰");}//重写父类的Operation方法public void operate(){super.operate();this.method2();}
}//场景类
public class Client {public static void main(String[] args) {Component component = new ConcreteComponent();//第一次修饰component = new ConcreteDecorator1(component);//第二次修饰component = new ConcreteDecorator2(component);//修饰后运行component.operate();}}