人靠衣装马靠鞍
1.定义(官方的)
- 装饰者模式可以动态地给一个对象增加其他职责。就扩展对象功能来说,装饰者模式比生成子类更为灵活。
- The Decorator Pattern attaches additional responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality.(有时候英文原版的比翻译过来更容易理解)
2.类图
-
Component类
定义对象接口,可以给这些动态地添加职责
-
ConcreteComponent类
定义具体的对象,Decorator类可以为其动态地添加职责
- Decorator类
- 维护一个指向Component对象实例的引用,并实现了与其一样的接口
-
ConcreteDecorator类
定义了具体的装饰类,给内部的具体对象添加职责
3. 代码实现
3.1 Component类
abstract class Component{
//定义对象职责
public abstract void Operation();
}
3.2 ConcreteComponent类
public class ConcreteComponent extends Component{
@override
public void Operation(){
// do something
}
}
3.3 Decorator类
// 定义装饰类,作为具体装饰类的抽象接口
public abstract class Decorator extends Component{
// 指向Component实例的引用
protected Component component ;
public void setComponent(Component component){
this.component = component ;
}
@override
public void Operation(){
if( component != null){
//重写Operation(),实际执行的是component的Operation()
component.Operation();
}
}
}
3.4 ConcreteDecorator类
public class ConcreteDecorator extents Decorator{
//具体的实现类中可以加入想要的属性或方法
public void Operation(){
base.Operation(); //首先执行原Component对象的operation()
add(); //然后执行本类的装饰行为,相当于对原component进行了装饰
}
}
3.5 DecoratorTest类
public class DecoratorTest{
public static void main(String[] args){
ConcreteComponent cmp = new ConcreteComponent();
ConcreteDecoratorA cda = new ConcreteDecoratorA();
ConcreteDecoratorB cdb = new ConcreteDecoratorB();
cda.setComponent(cmp);
cdb.setComponent(cda);
cdb.Operation();// 执行顺序:cmp.Operation()-->cda.Operation()-->cdb.Operation()
}
}
4.模式总结
- 装饰模式利用setComponent()对对象进程封装,使对象的实现和使用分离,每个被装饰对象只需关注自己的功能而不用关心自己是如何被加入对象链中。
- 装饰模式对原系统中的核心功能或进行了很好的装饰,在需要某种特殊的功能时装饰模式可以很好地对要装饰的对象进行包装,在不需要时可以随时撤除。
- 装饰模式适用于(但不一定都适用)以下情况
- 需要扩展一个类的功能,或给一个类添加附加职责。
- 需要动态的给一个对象添加功能,这些功能可以再动态的撤销。
- 需要增加由一些基本功能的排列组合而产生的非常大量的功能,从而使继承关系变的不现实。
- 当不能采用生成子类的方法进行扩充时。一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。另一种情况可能是因为类定义被隐藏,或类定义不能用于生成子类。如下图情况:
- 这样的类图组织看了之后,不疯即傻。。。