Вопрос

Я только начинаю изучать шаблоны дизайна, и у меня есть два вопроса, связанных с Декоратором...

Мне было интересно, почему шаблон декоратора предполагает, что декоратор реализует все общедоступные методы компонента, который он украшает?

Разве класс decorator нельзя просто использовать для предоставления дополнительных поведений, а затем конкретный компонент (который передается в него) просто использовать для вызова всего остального?

И, во-вторых, что, если конкретный компонент, который вы хотите украсить, не имеет базового класса, от которого абстрактный декоратор также может быть производным?

Заранее спасибо!

Это было полезно?

Решение

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

class Base {

  function foo() {
    return "foo";
  }

  function bar() {
    return "bar";
  }

}

// Not what we think of as a Decorator,
// really just a subclass.
class Decorator extends Base {

  // foo() inherits behavior from parent Base class 

  function bar() {
    return parent::bar() . "!"; // add something
  }

}

Класс декоратора не расширять базовый класс его "оформленного" класса.Это другой тип, который имеет объект-член оформленного класса.Таким образом, он должен реализовать тот же интерфейс, хотя бы для вызова соответствующего метода оформленного объекта.

class Decorator { // extends nothing
  protected $base;

  function __construct(Base $base) {
    $this->base = $base;
  }

  function foo() {
    return $base->foo();
  }

  function bar() {
    return $base->foo() . "!"; // add something
  }

}

Возможно, было бы целесообразно определить интерфейс (если ваш язык поддерживает такую вещь) как для оформленного класса, так и для класса Decorator .Таким образом, вы можете проверить во время компиляции, что Декоратор реализует тот же интерфейс.

interface IBase {
  function foo();
  function bar();
}

class Base implements IBase {
  . . .
}

class Decorator implements IBase {
  . . .
}

Ре:комментарий @Йоси Дахана:Я вижу двусмысленность в статье Википедии, но если вы внимательно прочитаете, там действительно говорится, что оформляемый компонент является поле в объекте decorator и что компонент передается в качестве аргумента конструктору decorator.Это отличается от наследования.

Хотя в статье Википедии действительно говорится, что декоратор наследуется от компонента, вы должны думать об этом как о реализации интерфейса, как я показал в примере PHP выше.Декоратору все еще приходится прокси-сервер для объекта component, чего бы он не сделал, если бы унаследовал.Это позволяет декоратору украсить объект Любой класс, который реализует этот интерфейс.

Вот несколько выдержек из "Шаблонов проектирования:Элементы многоразового объектно-ориентированного программного обеспечения" Гаммы, Хелма, Джонсона и Влиссидеса:

Декоратор

Намерение

Прикреплять дополнительные обязанности к объекту динамически.Декораторы предоставляют гибкую альтернативу подклассам для расширения функциональности.

Мотивация

...Декоратор соответствует интерфейсу компонента, который он украшает, так что его присутствие прозрачно для клиентов компонента.

Участники

  • Декоратор поддерживает ссылку на объект компонента и определяет интерфейс который соответствует интерфейсу компонента.

Другие советы

Мне было интересно, почему шаблон декоратора предполагает, что декоратор реализует все общедоступные методы компонента, который он украшает?

Декоратор должен быть заменой компоненту, который он украшает, с дополнительной функциональностью ("украшение").Это может произойти только в том случае, если он полностью реализует интерфейс компонента.

Разве класс decorator нельзя просто использовать для предоставления дополнительных поведений, а затем конкретный компонент (который передается в него) просто использовать для вызова всего остального?

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

И, во-вторых, что, если конкретный компонент, который вы хотите украсить, не имеет базового класса, от которого абстрактный декоратор также может быть производным?

Декораторы обычно наследуют класс компонента, который они украшают, а не базовую часть компонента.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top