首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >使用多个装饰器向对象添加功能?

使用多个装饰器向对象添加功能?
EN

Stack Overflow用户
提问于 2011-04-05 11:24:27
回答 1查看 2.9K关注 0票数 6

我试图理解装饰器模式,并从示例中了解装饰器对象是如何通过重写修饰对象的方法在运行时扩展现有功能的,以及它们如何通过新的方法实现添加附加功能。

我有点困惑的地方是在哪里使用了多个装饰器,以及如何访问扩展的功能。通常,当查看装饰图案的示例时,如下所示:

代码语言:javascript
运行
复制
IBusinessObject businessObject = new MailDecorator(
    new SmsDecorator(
        new FaxDecorator(
            new BusinessObject()
        )
    )
);

其思想是获取一个对象并动态添加邮件、短信和传真功能。现在,如果您想发送邮件,这是MailDecorator类提供的一种方法,您可以这样做:

代码语言:javascript
运行
复制
If(businessObject is MailDecorator)
{
    ((MailDecorator) businessObject).SendMail();
}  

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

这是装饰模式的一个限制,还是超出了您期望通过这种模式实现的范围?还是我完全误解了这里的一些内容?

不同的模式会更合适吗?

标准定义

“动态地将附加责任附加到对象上。装饰师为扩展功能提供了一种灵活的子类选择“

这意味着这个模式应该是可以实现的,但是当在一个对象上使用多个装饰器时,就会出现故障。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2011-04-05 11:46:03

这是装饰图案的一个常见误解。您可以使用装饰器模式来扩展functionality,,而不是API

这是什么意思?

这意味着,您可以向API提供的方法中添加新功能,在您的例子中是IBusinessObject。假设您的接口有一个方法XmlDocument Export(),该方法在BusinessObject中实现,并在XmlDocument实例中返回BusinessObject实例中的数据。

现在,您可以创建一个LoggingDecorator,它实现如下所示的Export方法:

代码语言:javascript
运行
复制
public XmlDocument Export()
{
    _logger.Log("Exporting...");
    var result = _decoratedObject.Export();
    _logger.Log("Done exporting...");
    return result;
}

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

代码语言:javascript
运行
复制
public XmlDocument Export()
{
    var result = _decoratedObject.Export();
    return SignXmlDocument(result);
}

然后,你可以像这样把它们放在一起:

代码语言:javascript
运行
复制
IBusinessObject businessObject = new LoggingDecorator(
    new BusinessObjectSigningExportDecorator(
        new BusinessObject()
    )
);

var xmlDocument = businessObject.Export();

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

使用装饰器模式的原因是能够透明地添加功能。如您所见,类型为businessObjectIBusinessObject变量的用户不知道也不需要知道实际使用的类型。不管有没有装潢师,它都适用于这种情况。

进一步考虑:当您有一个返回IBusinessObject的工厂时,您可以扩展该功能,而无需更改使用它们的代码,也不需要更改类的实现--实现IBusinessObject。您只需创建另一个装饰器并将其“附加”到工厂中,因此,您正在进行更改,这只发生在代码的有限区域内。因此,如果这个更改破坏了什么,您就会确切地知道是什么代码造成了破坏。

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

票数 16
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5551029

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档