设计模式之装饰模式
引入
Sunny 软件公司基于面向对象技术开发了一套图形界面组件库,该
组件库提供了大量的基本组件,如:
- 窗体(Window)
- 文本框(TextBox)
- 列表框(ListBox)
- ……
在使用该组件库时,用户经常要求定制一些特效显示效果,如:
- 带滚动条的窗体(ScrollBarWindow)
- 带黑色边框的文本框(BlackBorderTextBox)
- 既带滚动条又带黑色边框的列表框(ScrollBarAndBlackBorderListBox)
- ……
初始设计方案
可以看出,该设计通过增加子类来实现功能的扩展。
该设计方案存在如下问题:
- 系统不易扩展,且在某些语言中无法实现
- 我们可以看出,该设计方案通过增加子类来扩充功能,而在大多数语言中是无法实现多继承的,也就是说无法实现该设计方案。例如:如果要增加一个透明窗体类,同时 拥有三项功能(带滚动条、黑色边框、透明),则需要增加一个类,作为三个窗体类的子类,而这种多继承在大多数语言中无法实现
- 代码重复
- 我们可以看出,对于用于ScrollBar的每一个组件都拥有SetScrollBar()方法,而实际上该方法是相同的,这就造成了大量的冗余代码,不利用系统的维护和修改
- 系统庞大、类的种类过多
- 就上面的设计方案而言,我们要实现3种控件以及2种扩展方式,需要实现9个具体类,如果我们要再增加一个组件,则需要增加三个实体类,当控件和扩展方式较多时,无疑会使系统中类的数量很大,不利于维护。
设计方案的改进
我们依据 合成复用原则和里氏代换原则来对上述设计方案进行改进。
- 合成复用原则:实现功能复用时,多用关联关系,少用继承关系
- 里氏代换原则:在使用子类的地方都可以透明地使用父类
新的设计方案如下:
-
定义一个抽象类Component,实现对不同子类,以及装饰前控件以及装饰后控件的统一处理,符合里氏代换原则
-
定义一个Component的子类ComponentDecorator,作为装饰类,将控件注入其中(关联关系),从而通过装饰类的子类对控件的功能进行扩展。避免了产生大量冗余代码,符合合成复用原则
代码如下:
using System;
public abstract class Component{
public abstract void Display();
}
public class Window : Co