2.4 Decorator模式
2.4.1 功能
装饰模式又名包装(Wrapper)模式,装饰模式以对客户透明的方式动态的给一个对象附加上更多的责任。
这个模式有意思的地方在于:在基类可以出现的任何地方都可以有“装饰”。
怎么做到对客户透明呢?其实GoF的例子还是非常有代表性的,比网上的代码例子都更有说服力,虽然如此,最后还是要抄一个例子出来,接触了代码才算是“落地”了。
假如我们要做一个文本编辑器:
Windows::SetContents(VisualComponent *vC)
{
vC->draw();
//……
}
“最终用户”(注意这里指的是使用文本编辑器的用户,不是使用类库的用户)可以随意的指定是否有文本边框,是否有下拉框。那么,在这种模式下,如果“最终用户”指定了有下拉框+文本边框来“装饰”文本编辑器,那么“类库的用户”可以写如下代码:
Windows::SetContents(new ScrollDecorator(newBorderDecrator(new TextView)));
如果“最终用户”指定了只要下拉框来“装饰”文本编辑器,那么“类库用户”可以写如下代码:
Windows::SetContents(new ScrollDecorator(new TextView));
假如又有了别的装饰,比如状态栏等,同样可以再装饰一层。
这保证了Windows::SetContents这个客户代码的稳定性,即在基类可以出现的任何地方都可以有“装饰”。
2.4.2 结构
协作: D e c o r a t o r将请求转发给它的C o m p o n e n t对象,并有可能在转发请求前后执行一些附加的动作。
2.4.3 Java代码示例
//抽象构件接口,规范准备接收附加责任的对象
public interface Component
{
public void doSomething();
}
//具体构件角色
public class ConcreteComponent implements Component
{
@Override
public void doSomething()
{
System.out.println("功能A");
}
}
//装饰角色:持有一个构件(Component)对象的引用
public class Decorator implementsComponent
{
private Componentcomponent;
public Decorator(Componentcomponent)
{
this.component = component;
}
@Override
public void doSomething()
{
component.doSomething();
}
}
//具体装饰角色1,负责给构件对象"贴上"附加的责任,即添加新的功能
public class ConcreteDecorator1 extends Decorator
{
publicConcreteDecorator1(Component component)
{
super(component);
}
@Override
public void doSomething()
{
super.doSomething();
this.doAnotherThing();
}
private void doAnotherThing()
{
System.out.println("功能B");
}
}
//具体装饰角色2
public class ConcreteDecorator2 extends Decorator
{
publicConcreteDecorator2(Component component)
{
super(component);
}
@Override
public void doSomething()
{
super.doSomething();
this.doAnotherThing();
}
private void doAnotherThing()
{
System.out.println("功能C");
}
}
//装饰模式测试类:
public class TestDecorator
{
public static void main(String[] args)
{
Component component = new ConcreteDecorator2(new ConcreteDecorator1(newConcreteComponent()));
component.doSomething();
}
}
输出结果:
功能A
功能B
功能C