代码示例:https://github.com/elfc/patterns
分类
类对象结构型
意图
动态地给一个对象添加一些额外地职责。就增加功能来说,Decorator模式相比生成子类更为灵活。
动机
Decorator模式可以在不修改对象外观和功能的情况下添加或者删除对象功能。它可以使用一种对客户端来说是透明的方法来修改对象功能,也就是使用初始的子类实例对初始对象进行授权。Decorator模式还为对象动态地添加了额外的责任,这样就在不使用静态继承的情况下,为修改对象功能提供了灵活的选择。
适用性
- 想要在单个对象中动态并且透明地添加责任,而这样并不会影响其他对象。
- 想要在以后可能要修改的对象中添加责任。
- 当无法通过静态子类化实现扩展时。
优点
- 比静态继承具有更大的灵活性。
- 避免了特征装载的类处于层次结构的过高级别。
- 简化了编码,因为用户编写的每一个类都针对功能的一个特定部分,而不用将所有的行为编码到对象中。
- 改进了对象的扩展性,因为用户可以通过编写新的类来作出改变。
结构
参与者
- Component(VisualComponent)
-- 定义一个对象接口,可以给这些对象动态地添加职责。 - ConcreteComponent(TextView)
-- 定义一个对象,可以给这个对象添加一些职责。 - Decorator
-- 维持一个指向Component对象的指针,并定义一个与Component接口一致的接口。 - ConcreteDecorator(BorderDecorator,ScrollDecorator)
-- 向组件添加职责
代码示例
一个图形用户界面工具箱(VisualComponent)允许你对任意一个用户界面组件添加一些特性,例如边框(BorderDecorator),或是一些行为,例如窗口滚动(ScrollDecorator)。
有一个对象TextView,它可以在窗口中显示正文。缺省的TextView没有滚动条。当需要滚动条时,我们可以用ScrollDecorator添加滚动条。还可以使用BorderDecorator给带滚动条的文本对象添加一个边框。
/**
* @author chunyuliu
*/
public interface VisualComponent {
void draw();
}
/**
* @author chunyuliu
*/
public class TextView implements VisualComponent {
@Override
public void draw() {
System.out.println("TextView");
}
}
/**
* @author chunyuliu
*/
public class Decorator implements VisualComponent {
private VisualComponent visualComponent;
public Decorator(VisualComponent visualComponent) {
this.visualComponent = visualComponent;
}
@Override
public void draw() {
this.visualComponent.draw();
}
}
/**
* @author chunyuliu
*/
public class BorderDecorator extends Decorator {
public BorderDecorator(VisualComponent visualComponent) {
super(visualComponent);
}
@Override
public void draw() {
drawBorder();
super.draw();
}
private void drawBorder() {
System.out.println("边框");
}
}
/**
* @author chunyuliu
*/
public class ScrollDecorator extends Decorator {
public ScrollDecorator(VisualComponent visualComponent) {
super(visualComponent);
}
@Override
public void draw() {
scrollTo();
super.draw();
}
private void scrollTo() {
System.out.println("滚动条");
}
}
测试用例
/**
* @author chunyuliu
*/
public class DecoratorTest {
@Test
public void textViewTest() {
// 原始文本对象
VisualComponent textView = new TextView();
// 给文本增加滚动条
VisualComponent scrollTextView = new ScrollDecorator(textView);
// 给有滚动条的文本增加边框
VisualComponent borderScrollTextView = new BorderDecorator(scrollTextView);
borderScrollTextView.draw();
}
}