Это распространенное заблуждение шаблона декоратора. Что вы можете сделать с шаблоном декоратора, так это расширить функциональность , а не API .
Что это значит?
Это означает, что вы можете добавить новую функциональность в методы, предоставляемые API, в вашем случае IBusinessObject
. Допустим, у вашего интерфейса есть метод XmlDocument Export()
, который реализован в BusinessObject
и возвращает данные в экземпляре BusinessObject
в экземпляре XmlDocument
.
Теперь вы можете создать LoggingDecorator
, который реализует метод Export
следующим образом:
public XmlDocument Export()
{
_logger.Log("Exporting...");
var result = _decoratedObject.Export();
_logger.Log("Done exporting...");
return result;
}
Или вы можете создать BusinessObjectSigningExportDecorator
, который подписывает возвращаемое XmlDocument
, используя алгоритм xml-dsig:
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
без декоратора или только с одним из декораторов.
Причиной использования шаблона декоратора является возможность прозрачного добавления функциональности. Как видите, пользователь переменной businessObject
типа IBusinessObject
не знает и не должен знать фактический используемый тип. Это будет работать в случае с или без декораторов.
Подумайте дальше: если у вас есть фабрика, которая возвращает IBusinessObject
s, вы можете расширить функциональность, не меняя код, который их использует и , не изменив реализацию класса реализации IBusinessObject
. Вам просто нужно создать другой декоратор и «прикрепить» его внутри фабрики, и поэтому вы вносите изменения, которые происходят только в ограниченной области кода. Таким образом, если это изменение что-то нарушает, вы точно знаете, какой код отвечает за поломку.
Кроме того, это обеспечивает разделение интересов, потому что ваша обычная реализация бизнес-объекта не знает и не заботится о том, какой алгоритм подписи следует использовать или что нужно использовать вообще.