使用多个装饰器为对象添加function?

我试图理解装饰器模式,从实例中我了解装饰器对象如何通过覆盖装饰对象的方法以及如何通过新方法实现添加其他function来在运行时扩展现有function。

我有点困惑的地方是使用多个装饰器以及如何访问扩展function。 通常,在查看装饰器模式的示例时,会显示如下所示:

IBusinessObject businessObject = new MailDecorator( new SmsDecorator( new FaxDecorator( new BusinessObject() ) ) ); 

想法是采取一个对象并动态添加邮件,短信和传真function。 现在,如果您想发送邮件,这是MailDecorator类提供的方法,您可以执行以下操作:

 If(businessObject is MailDecorator) { ((MailDecorator) businessObject).SendMail(); } 

但是,如果您想要发送SMS或传真,就像在装饰器模式的正常实现中那样,您将无法访问装饰器引用的对象,这将无效。

这是装饰器模式的限制还是超出了你可以期望用这种模式实现的范围,还是我完全误解了这里的东西?
不同的模式会更合适吗?

标准定义

“动态地将附加职责附加到对象。 装饰器提供了一种灵活的替代子类,以扩展function“

暗示这应该可以通过这种模式实现,但在一个对象上使用多个装饰器时似乎会崩溃。

这是装饰者模式的常见误解。 你可以用装饰器模式做的是扩展function ,而不是API

这是什么意思?
这意味着,您可以在您的IBusinessObject案例中为API提供的方法添加新function。 假设您的接口有一个方法XmlDocument Export() ,它在BusinessObject实现,并返回XmlDocument实例中的BusinessObject实例中的数据。
现在,您可以创建一个LoggingDecorator ,它实现了Export方法,如下所示:

 public XmlDocument Export() { _logger.Log("Exporting..."); var result = _decoratedObject.Export(); _logger.Log("Done exporting..."); return result; } 

或者,您可以创建一个BusinessObjectSigningExportDecorator ,它使用xml-dsig算法对返回的XmlDocument进行签名:

 public XmlDocument Export() { var result = _decoratedObject.Export(); return SignXmlDocument(result); } 

然后你可以像这样一起使用它们:

 IBusinessObject businessObject = new LoggingDecorator( new BusinessObjectSigningExportDecorator( new BusinessObject() ) ); var xmlDocument = businessObject.Export(); 

Export的调用现在将写入日志消息并签署xml导出。 但是您仍然可以在没有装饰器的情况下使用BusinessObject ,或者只使用其中一个装饰器。

使用装饰器模式的原因是能够透明地添加function。 如您所见, IBusinessObject类型的businessObject变量的用户不知道也不需要知道所使用的实际类型。 它适用于有或没有装饰器的情况。

进一步思考:当您拥有一个返回IBusinessObject的工厂时,您可以扩展function,而无需更改使用它们的代码, 无需更改实现IBusinessObject类的实现。 您只需要创建另一个装饰器并在工厂内“附加”它,因此,您正在进行更改,这仅在代码的有限区域内发生。 因此,如果此更改破坏了任何内容,您就会确切知道哪些代码会导致破坏。

此外,这会强制关注点分离,因为您的正常业务对象实现不知道并关心应该使用哪种签名算法或者需要完全使用哪种签名算法。