Подтвердить что ты не робот

Разница между дизайном дизайна декоратора и шаблоном дизайна посетителей

Я считаю, что понимаю цель дизайна дизайнера и посетителя.

Хотя я могу перечислить следующие различия

  • Декоратор работает над объектом, посетитель работает над составной структурой,
  • Decorator - это шаблон структурного дизайна, посетитель - шаблон поведения.

Когда я думаю в глубине души, я не могу убедить себя в том, что представляет собой реальную разницу между ними.

4b9b3361

Ответ 1

Ну, они на самом деле такие же разные, как они могут быть!

Вы используете Decorator, если хотите улучшить существующий объект с помощью новых, более или менее прозрачных функций, таких как проверка или кеширование. См. Пример здесь: Должен ли я расширять ArrayList для добавления атрибутов, которые не являются нулевыми?

Посетитель, с другой стороны, используется, когда у вас есть иерархия классов, и вы хотите использовать другой метод на основе конкретного типа, но избегая операторов instanceof или typeof. См. Пример в реальной жизни: Используется ли это использование "instanceof" Оператор считает плохой дизайн?

Декоратор работает над объектом, Visitor работает над композитной структурой,

Посетитель работает в иерархии наследования, Composite - это другой шаблон дизайна GoF.

Decorator - это шаблон структурного дизайна, посетитель - шаблон поведения.

Правда, но это не помогает понять, как они работают?

См. также

Ответ 2

Шаблоны проектирования не предназначены для категоризации различий в реализации, а при использовании одного или другого.

Они служат для совершенно разных целей:

  • вы будете использовать декоратор, если хотите динамически обогащать функциональность объектов, предоставляя отдельные элементы, которые украшают другие объекты, чтобы они действительно добавляли к ним некоторое поведение (на самом деле это структурный шаблон в том смысле, что он изменяет структуру объектов, которые вы вставляете)
  • вы будете использовать посетителя, если хотите отделить алгоритм от объектов, с которыми он используется. Что вы делаете, так это то, что у вас есть этот посетитель, который передается множеству разных объектов, обычно это иерархия (говорят, что они принимают посетителя), этот посетитель выполняет определенные операции в зависимости от типа объектов, которые он посещает в конкретном момент. Таким образом, вы можете заставить своего посетителя делать все, что захочет, с конкретными объектами без необходимости указывать эти операции в самих объектах (почему он поведенческий). Это своего рода абстрактные методы, которые не определены в самом объекте.

Ответ 3

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

abstract class Chef{
  public abstract void Prepare();
}

class CookieMaker:Chef{         //Concrete class
   public override void Prepare()
    {
        //Bake in Oven
     }
 }

  // Decorator class
 // This chef adds chocolate topping to everything
 class ChocoChef:Chef{  

     public ChocoChef(Chef mychef)
     {
        this.chef = mychef; 
     }

     public override void Prepare()
     {
           // Add chocolate topping first
           chef.Prepare()
     } 
 }

Я сократил некоторые детали ради пространства. Например, вы могли бы абстрагироваться с шеф-поваром, который добавляет какой-либо вид сверху, а ChocoChef становится его конкретным классом. Теперь ChocoChef всегда добавляет шоколадные начинки, независимо от того, что вы готовите. Итак, теперь вы можете иметь шоколадное печенье или шоколадный торт, передав подходящего шеф-повара своему конструктору. Посетитель, с другой стороны, действует на объекты и решает сделать что-то на основе объекта, который он посещает.

class Student{
     // Different visitors visit each student object using this method
     // like prize distributor or uniform inspector
     public Accept(IVisitor v)
     {
         v.Visit(this)
     }
}

 // Visitor visits all student OBJECTS
class PrizeDistributor:IVisitor{
     public override void Visit(Student s)
     {
           //  if(s has scored 100)
           // Award prize to s
     }
}

Ответ 4

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

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

Ответ 5

Они оба "добавляют функциональность" к существующему объекту, не изменяя исходный класс. Разница заключается в следующем:

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

С посетителем Вы добавляете совершенно новое поведение, которое вы не хотите определять как часть самого базового класса компонента (даже не как оболочку для базовых функций), например, из-за одиночного принцип ответственности, принцип открытого закрытия и т.д. Это особенно полезно, когда это поведение будет отличаться между разными подклассами одного и того же типа (если нет какой-либо сложной структуры подклассов, а только один класс, вы можете просто создать новый класс и включить исходный класс через композицию и достичь цели не влияя или не изменяя исходный класс). Таким образом, вы можете избежать кода типа if (a is ConcreteClass1) {...} else if (a is ConcreterClass2) {...} без написания виртуальных методов.

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

Ответ 6

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

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

Ответ 7

Decorator

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

Когда использовать шаблон Decorator?

  • Обязанности и поведение объекта должны динамически добавляться/удаляться
  • Конкретные реализации должны быть отделены от обязанностей и поведения
  • Когда подклассификация слишком дорогостоящая, чтобы динамически добавлять/удалять обязанности

Похожие сообщения:

Когда использовать шаблон декоратора?

Visitor:

Шаблон проектирования посетителей - это способ разделения алгоритма на структуру объекта, на которой он работает. Практическим результатом этого разделения является возможность добавления новых операций к существующим структурам объектов без изменения этих структур. Это один из способов следовать принципу "открытый/закрытый".

Когда использовать шаблон посетителя?

  • Подобные операции должны выполняться на объектах разных типов, сгруппированных в структуру
  • Вам нужно выполнить много разных и не связанных действий. Он отделяет операцию от объектов Структура
  • Новые операции должны быть добавлены без изменения структуры объекта.
  • Соберите связанные операции в один класс, а не заставляйте вас изменять или выводить классы.
  • Добавить функции в библиотеки классов, для которых у вас либо нет источника, либо невозможно изменить источник

Похожие сообщения:

Когда следует использовать шаблон дизайна посетителя?

Полезные ссылки:

sourcemaking статья декоратора

oodesign статья для посетителей

sourcemaking статья для посетителей

Ответ 8

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

Посетитель должен в первую очередь уважать OCP (а иногда и SRP), чтобы сделать систему более гибкой. Вы можете добавить любого посетителя, который вы можете, по мере того, как ваша программа развивается без изменения существующей системы. Однако вам необходимо заранее сконструировать систему . Вы не можете добавить новый класс (или шаблон) посетителя в уже запущенную систему и ожидать, что он будет работать без повторной компиляции, повторного тестирования или любого другого.

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

Какой из них предпочтительнее? ИМО, отвечая на это, может быть более полезным. Для меня мне не нравится стиль Decorator для использования базового класса. Он использует наследование и агрегацию. Если вам нужно изменить этот класс (wrapee), вы в конечном итоге перекомпилируете всю иерархию/модуль. Но это удобно, и вы можете изменить поведение после времени разработки. С другой стороны, в шаблоне Visitor мне не нравится идея узнать каждый конкретный тип в реализации Visitor. Когда вы добавляете новый тип базового класса, вам также нужно перейти и изменить класс посетителя, чтобы добавить его. Но это полезно, когда вам нужно вставить код в существующую систему без изменения структуры или вам нужно разделить проблемы в классе (однопользовательский ответ).

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