1. 意图
动态地给一个对象添加一些额外的职责。就增加功能来说,Decorator模式比生成子类更为灵活。
2. 别名
包装器 Wrapper
3. 动机
给某个对象而不是整个类添加一些功能。
4. 适用性
在不影响其他对象的情况下,以动态,透明的方式给单个对象添加职责。
处理那些可以撤销的职责。
当不能采用生成子类的方法进行扩充时。一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。另一种情况可能是因为类定义被隐藏,或类定义不能用于生成子类。
5. 类图
6. 代码
class Program
{
static void Main(string[] args)
{
IWindow window = new HorizontalScrollbarDecorator(new VerticalScrollbarDecorator(new SimpleWindow()));
window.Draw();
}
}
interface IWindow
{
void Draw();
string GetDescription();
}
class SimpleWindow : IWindow
{
public void Draw()
{
Console.WriteLine("draw a simple window");
}
public string GetDescription()
{
return "I am a simple window";
}
}
class WindowDecorator : IWindow
{
protected IWindow iWindow = null;
public WindowDecorator(IWindow iWindow)
{
this.iWindow = iWindow;
}
public void Draw()
{
iWindow.Draw();
}
public string GetDescription()
{
return iWindow.GetDescription();
}
}
class HorizontalScrollbarDecorator : WindowDecorator
{
public HorizontalScrollbarDecorator(IWindow iWindow)
: base(iWindow)
{
}
public void Draw()
{
base.Draw();
DrawHorizontalScrollbarDecorator();
}
private void DrawHorizontalScrollbarDecorator()
{
Console.WriteLine("draw a horizontal scrollbar");
}
public string GetDescription()
{
string result = base.GetDescription();
result += "a window with horizontal scrollbar";
return result;
}
}
class VerticalScrollbarDecorator : WindowDecorator
{
public VerticalScrollbarDecorator(IWindow iWindow)
: base(iWindow)
{
}
public void Draw()
{
base.Draw();
DrawVerticalScrollbarDecorator();
}
private void DrawVerticalScrollbarDecorator()
{
Console.WriteLine("draw a vertical scrollbar");
}
public string GetDescription()
{
string result = base.GetDescription();
result += "a window with vertical scrollbar";
return result;
}
}
8. 效果
Decorator模式的优点和缺点
1) 比静态继承更灵活
2) 可以避免在层次结构的高层类有太多的特性
3) Decorator类和Component类还是不一样的
4) 太多的Decorator容易产生很多小对象
9. 讨论
Decorator可以在运行时为对象动态的添加职责,关键点就在于Decorator与ConcreteComponen具有同样的接口
Decorator和Composite模式的区别在于Composite模式的一个类具有容器的特性,因此可以体现部分-整体的关系, 并且没有子类
Decorator的装饰类可以有子类,子类就是具体的装饰者
公共的Component应当尽量保持简单,它应当集中于定义接口而不是存储数据