В чем разница между миксином и шаблоном декоратора? - PullRequest
24 голосов
/ 06 апреля 2010

Шаблон Decorator - это динамическое расширение классов во время выполнения. Он динамически формирует отношения «есть».

Я начал задумываться, не усложнил ли я свой API с помощью шаблона Decorator после того, как получил этот ответ о разнице между миксином и абстрактным классом.

Ответы [ 3 ]

13 голосов
/ 06 апреля 2010

При использовании шаблона декоратора вы обычно инкапсулируете, а не расширяете (или смешиваете) базовый класс. Часто вы делаете это, потому что вы хотите использовать функциональные возможности класса, но вы хотите обернуть вызовы в него, чтобы вы могли сделать некоторые дополнительные шаги до или после вызова. Рассмотрим LoggerDecorator

public class LoggerDecorator implements SomeInterface {
      private SomeInterface delegate;
      public void someMethod() {
          LOGGER.debug("someMethod called");
          delegate.someMethod();
      }
}

Вы не хотите фактически выставлять делегата, но хотите использовать его функциональность. Так что, действительно ли вы используете миксины, расширяете класс или украшаете, зависит от того, что вы пытаетесь сделать. Вы расширяете класс и добавляете в него новые функциональные возможности? Или вы упаковываете / украшаете класс?

12 голосов
/ 06 апреля 2010

Миксин подходит, когда вы добавляете немного поведения в свой класс. например возможность перечисления в случае типа коллекции. Вы можете смешивать в своем классе столько наборов поведения, сколько захотите. Это хороший способ повторно использовать общий код; вы в основном получаете кучу методов бесплатно.

С другой стороны, декоратор - это скорее подлый перехватчик. Он предоставляет тот же открытый интерфейс, что и целевой объект, содержит целевой объект, которому он делегирует все клиентские вызовы; однако он украшает вызов с некоторой предварительной и / или последующей обработкой. например если я пишу код для MyCollection и хочу, чтобы все вызовы этого типа регистрировались. Я мог бы получить новый декоратор MyCollectionWithTimeStampedLogging, оба производные от базы ICollection, чтобы они выглядели идентично клиенту. Декоратор может взять экземпляр ICollection в качестве параметра ctor и передать ему вызовы. например Добавить будет выглядеть так

public void Add( int item)
{
  _logger.log(String.Format( "{0} Add called with param {1}", DateTime.Now, item.ToString());
  _collection.Add(item);
  _logger.log(String.Format( "{0} Add completed with param {1}", DateTime.Now, item.ToString());
}
3 голосов
/ 06 апреля 2010

Я не уверен, что согласен с утверждением, что Decorator распространяется во время выполнения. Я знаю, что это то, что говорит Википедия, но я не думаю, что это точно. Я бы посоветовал прочитать определение GoF шаблона Decorator. Да, это динамическое расширение, но оно не обязательно должно быть во время выполнения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...