装饰器 (Decorator)





0/5 (0投票)
装饰器模式允许在运行时动态地改变对象的行为。这种行为的改变是通过将一个
装饰器模式允许在运行时动态地改变对象的行为。
这种行为的改变是通过用一个新的对象包装旧对象来实现的。这个新的包装对象就是装饰器。装饰器对象将实现与被包装对象相同的接口。因为被装饰的对象使用与未装饰对象相同的接口,所以您系统的其他部分不需要知道是否使用了零个或多个装饰。
装饰器(包装器)现在可以通过完全替换各种方法或改变被装饰对象的方法的行为来改变被包装对象Thus behavior.
示例
装饰器的简单示例可以用报告类来演示。有些报告可能需要页眉,有些可能需要页脚。还有些可能需要页眉和页脚。
首先,因为装饰器需要实现与被装饰对象相同的接口,所以让我们定义一个接口。
Public Interface IReport
Sub Print()
End Interface
现在我们可以创建一个实现该接口的非常简单的报告类。
Public Class Report
Implements IReport
Public Sub Print() Implements IReport.Print
HttpContext.Current.Response.Write("This is the report body.")
End Sub
End Class
接下来,我们可以创建一个装饰器类来为我们的报告添加页眉。因为我们的装饰器将包装我们的报告,所以它需要一个报告实例传递到其构造函数中。
Public Class ReportHeaderDecorator
Implements IReport
Private _innerReport As IReport
Public Sub New(ByVal innerReport As IReport)
'保存被装饰对象的引用
_innerReport = innerReport
End Sub
Public Sub Print() Implements IReport.Print
'先添加页眉装饰
HttpContext.Current.Response.Write("<h3>This is the report header</h3>")
HttpContext.Current.Response.Write("<hr />")
'现在让被装饰的报告进行打印
_innerReport.Print()
End Sub
End Class
我们还可以创建另一个装饰器来为我们的报告添加页脚。
Public Class ReportFooterDecorator
Implements IReport
'保存被装饰对象的引用
Private _innerReport As IReport
Public Sub New(ByVal innerReport As IReport)
_innerReport = innerReport
End Sub
Public Sub Print() Implements IReport.Print
'先让被装饰的报告进行打印
_innerReport.Print()
'现在我们添加页脚装饰
HttpContext.Current.Response.Write("<hr />")
HttpContext.Current.Response.Write("<h6>This is the report footer.</h6>")
End Sub
因为 Report 类和装饰器都实现了相同的 IReport 接口,所以常规报告和装饰报告可以在接受 IReport 的任何地方使用。下面是如何创建一个报告,然后用装饰器包装它。
Dim myReport As IReport
myReport = New Report '创建基本报告
myReport = New ReportHeaderDecorator(myReport) '用页眉装饰包装
myReport = New ReportFooterDecorator(myReport) '用页脚装饰包装
myReport.Print()
打印此报告的结果将如下所示
This is the report header
This is the report body.
This is the report footer.
通过继承也可以达到类似的效果。这将需要我们的 Report 类的 3 个子类。一个 ReportWithHeader 子类,一个 ReportWithFooter 子类,还有一个 ReportWithHeaderAndFooter 子类。随着需要越来越多的装饰,创建所有必要的子类来覆盖所有可能的组合将很快变得难以管理。
由于各种装饰器类可以在运行时组合,因此我们不必预先定义所有可能的组合。
对于 C#,示例代码如下所示
public interface IReport
{
void Print();
}
public class Report : IReport
{
public void IReport.Print()
{
HttpContext.Current.Response.Write("This is the report body.");
}
}
public class ReportHeaderDecorator : IReport
{
private IReport _innerReport;
public ReportHeaderDecorator(IReport innerReport)
{
//保存被装饰对象的引用
_innerReport = innerReport;
}
public void IReport.Print()
{
//先添加页眉装饰
HttpContext.Current.Response.Write("<h3>This is the report header</h3>");
HttpContext.Current.Response.Write("<hr />");
//现在让被装饰的报告进行打印
_innerReport.Print();
}
}
public class ReportFooterDecorator : IReport
{
//保存被装饰对象的引用
private IReport _innerReport;
public ReportFooterDecorator(IReport innerReport)
{
_innerReport = innerReport;
}
public void IReport.Print()
{
//先让被装饰的报告进行打印
_innerReport.Print();
//现在我们添加页脚装饰
HttpContext.Current.Response.Write("<hr />");
HttpContext.Current.Response.Write("<h6>This is the report footer.</h6>");
}
}
//实现装饰器
IReport myReport;
myReport = new Report();
//创建基本报告
myReport = new ReportHeaderDecorator(myReport);
//用页眉装饰包装
myReport = new ReportFooterDecorator(myReport);
//用页脚装饰包装
myReport.Print();