装饰模式
装饰(Decorator)模式又叫包装(Wrapper)模式。以对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案。
装饰模式以对客户端透明的方式动态的给一个对象附加更多的责任。客户端并不会角色对应在装饰前和装饰后有什么不同
1.1结构
装饰模式使用原来被装饰的类的一个子类的实例,把客户端的调用委派到被装饰类,装饰模式的关键在于这个扩展是完全透明的。
抽象构件(Component)角色:规范准备接受附加责任的对象。可以是接口、抽象类或者具体类。
具体构件(Concrete Component)角色:定义一个将要接收附加责任的类。
装饰(Decorator)角色:持有一个构件(component)对象的实例,并定义一个与抽象构件接口一致的接口。
具体装饰(Concrete Decorator)角色:负责给构件对象“贴上”附加的责任。
装饰模式常常被称为包装模式,因为每个具体装饰类都将一个具体装饰类或者具体构件诶包裹起来。装饰模式对客户端透明性要求程序不要声明一个ConcreteDecorator类型的变量,而应该声明一个Component类型的变量。然而纯粹的装饰模式很难找到,装饰模式的用意是不改变接口的前提下,增强所考虑的类的性能,这就导致大多数装饰模式都是“半透明”的,即允许装饰模式改变接口,增加新的方法。客户端可以声明ConcreteComponent类型的变量,从而可以调用ConcreteDecorator类中才有的方法。
半透明的装饰模式介于装饰模式和适配器模式之间。
抽象构件角色:
/** * 抽象构件角色 */ public interface Component { /** * 商业方法 */ void operate(); }
具体构件角色:
/** * 具体构件角色 */ public class ConcreteComponent implements Component { @Override public void operate() { System.out.println("concreteComponent operate ..."); } }
装饰角色:
/** * 装饰角色 */ public class Decorator implements Component { private Component component; public Decorator(Component component) { this.component = component; } @Override public void operate() { component.operate(); } }
具体装饰角色:
/** * 具体装饰类 */ public class ConcreteDcorator extends Decorator { public ConcreteDcorator(Component component) { super(component); } @Override public void operate() { super.operate(); } }
1.2使用
1)需要扩展一个类的功能,或给一个雷增加附加责任。
2)需要动态的给一个对象增加功能,这些功能可以动态的撤销。
3)增加由一些基本功能的排列组合而产生的非常大量的信功能,从而使继承关系变得不现实。
1.3优点
1)装饰模式与继承关系的目的都是扩展对象的功能,但是装饰模式可以提供比继承更多的灵活性。
继承关系是静态的,在系统运行前就决定了,而装饰模式可以动态的决定“贴上”一个需要的“装饰”,或者除掉一个不需要的“装饰”。
2)通过使用不同的具体装饰类以及这些装饰类的排列组合创造出很多行为的不同组合。继承关系则没有这种优势,每个不同排列组合需要事先通过子类的继承方式设计好。
3)比继承由更大的灵活性,但也更易出错。
1.4缺点
装饰模式比使用继承需要的类少,但是产生的对象更多,使差错困难。
1.5简化
省略抽象构件角色:
只有一个ConcreateComponent时,可以省略抽象构件角色。此时Decorator可以是ConcreteComponent的子类。
省略Decorator:
没有Component,ConcreteComponent扮演了双重角色。
只有一个ConcreteDecorator时,可以省略Decorator,此时ConcreteDecotor扮演了双重角色。
参考:
《java与模式》