2015-01-01 1 views
1

Глядя на странице шаблона Decorator на википедии (http://en.wikipedia.org/wiki/Decorator_pattern), макет выглядит примерно так:Может ли декораторы быть прямым ребенком компонента?

  • компонентов интерфейса реализации
  • Компонент
  • интерфейс декоратор, который реализует интерфейс компонентов
  • декоратора (s), которые реализуют интерфейс декоратора

Может ли декораторы вместо этого непосредственно реализовать компонент интерфейс (и пропустить интерфейс декодера)?

+0

Какие программирования О каком языке речь? –

+0

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

+0

@neverendingqs нет интерфейса декоратора, есть дополнительный _abstract_ decorator. – qujck

ответ

0

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

ThingDoer thingDoer = new ThingDoerDecorator(new AwesomeThingDoer()); 
ThingDoer otherThingDoer = new AwesomeThingDoer(); 

thingDoer.doThing(); 
otherThingDoer.doThing(); 

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

Однако иногда имеет смысл иметь базовый декоратор, реализующий.

abstract class BaseThingDoerDecorator implements ThingDoer { 
    private ThingDoer thingDoer; 

    protected BaseDecorator(ThingDoer thingDoer) { 
     this.thingDoer = thingDoer; 
    } 

    @Override 
    public void doThing() { 
     thingDoer.doThing(); 
    } 
} 

Теперь становится практичным, чтобы сделать такие вещи, как это:

ThingDoer thingDoer = new BaseThingDoerDecorator(new AwesomeThingDoer()) { 
    @Override 
    public void doThing() { 
     System.out.println("This is an anonymous decorator"); 
     super.doThing(); 
    } 
}; 

Или, может быть, вы хотите, чтобы все ваши декораторы быть защищены от исключений в базовом компоненте:

abstract class BaseThingDoerDecorator implements ThingDoer { 
    // Same as above... 
    // ... 
    @Override 
    public void doThing() { 
     try { 
      thingDoer.doThing(); 
     } catch (Exception e) { 
      log(e); 
     } 
    } 
} 
+0

Просто, чтобы уточнить @Floegipoky, это ответ: «Да, декораторы являются прямым дочерним элементом компонента. Однако вот несколько примеров, где вы хотите использовать абстрактный класс».? – neverendingqs

+0

@neverendingqs Нет, мой ответ заключается в том, что декораторы должны * реализовать * интерфейс компонента, но вот несколько примеров, когда для них есть смысл * наследовать * из базового класса. – Floegipoky

+0

Хм это то, что я хотел сказать, но моя грамматика и формулировка были не самыми лучшими в этом вопросе. В любом случае, ваш ответ уточняет, что я ищу. – neverendingqs

0

Вот UML диаграмма со страницы википедии вы цитируемой:

Decorator pattern in UML

На этой диаграмме, декоратор не интерфейс, но абстрактный класс. Компонент также является не интерфейсом на этой диаграмме (так как ConcreteComponent и Декораторы, наследующие от него, не имеют пунктирных линий со стрелки на диаграмме). Я знаю, что это деталь, но UML определен по какой-то причине.

Таким образом, любой ConcreteDecorator может наследовать непосредственно из Component (или реализовать его интерфейс, если ваш проект использует интерфейс) без использования абстрактного класса Decorator . Тем не менее, all ConcreteDecorators необходимо объединить компонент, поэтому абстрактный класс может быть полезен, чтобы избежать дублирования кода, если у вас есть несколько ConcreteDecorator.

+0

Я бы фактически утверждал, что диаграмма неверна. Если бы образец был реализован таким образом, каждый декоратор имел бы 2 компонента. Единственный способ избежать лишних накладных расходов - сделать базовый компонент (тот, который декоратор «является») полностью пустым, что делает его интерфейсом во всем, кроме имени. Это может быть эффективным способом ломать его на языки, которые не имеют интерфейсов, но это вводит в заблуждение и, конечно же, не должно использоваться для авторитетной модели шаблона. – Floegipoky

+0

Я вижу только один компонент @Floegipoky. Где второй? – Fuhrmanator

+0

Декораторы «обертывают» компоненты, поэтому я не вижу, как интерфейс имеет смысл вместо Декоратора. Дизайн здесь выглядит как тот, что был из GoF, который был предложен до того, как существовали интерфейсы на Java или C#. Пожалуйста, цитируйте свою авторитетную ссылку, @Floegipoky – Fuhrmanator

Смежные вопросы