Шаблон посетителя - добавить новые классы ConcreteElement сложно?
Я прочитал книгу о шаблоне посетителя. Он дает ту же диаграмму классов, что и на сайте oodesign.
Это говорит о том, что добавить новые классы ConcreteElement сложно. Но я не поняла почему. Как я понял, Concretevisitor определяет набор операций, которые должны использоваться конкретным элементом. Поэтому, когда я добавляю новый элемент, который выполняет ту же операцию, которую я определил ранее, мне не нужно ничего добавлять (только сам ConcreteElement). Если я добавляю новый элемент, в котором нет тех операций, которые я определил ранее для посетителей, мне нужно добавить нового посетителя. Но это я должен сделать в любом шаблоне дизайна.
4 ответа
Ну, вы должны расширить всех ваших посетителей.
У вас есть вызывающая сторона, некоторые элементы, которые необходимо посетить, и элемент - посетитель, который выполняет обработку отдельных элементов. Ваша цель состоит в том, чтобы сохранить реализацию элементов и вызывающего абонента фиксированной, а также расширить функциональность с помощью новых посетителей.
Обычно у вас много конкретных посетителей. Если вы добавите новый тип элемента для обработки, вам нужно будет изменить всех конкретных посетителей, чтобы принять это во внимание.
Зачем?
хорошо, представьте, что вызывающим абонентом является "Фабрика", и у вас есть элементы "Автомобиль" и "Велосипед".
Для операции "Краска" необходимо иметь методы
void process(Car c); // Paint a car
void process(Bike b); // Paint a bike
Аналогично для операций "Сборка", "Упаковка", "Мойка" и т. Д.
Если вы добавите элемент "Scooter", все операции должны быть расширены новым методом
void process(Scooter s); // Handle a Scooter
Это немного работы. Также вы можете попасть туда, где элемент, который вы добавляете, настолько отличается от других, что вы не можете легко приспособить его к операциям.
Википедия (http://en.wikipedia.org/wiki/Visitor_pattern) говорит
По сути, посетитель позволяет добавлять новые виртуальные функции в семейство классов, не изменяя сами классы; вместо этого создается класс посетителя, который реализует все соответствующие специализации виртуальной функции. Посетитель принимает ссылку на экземпляр в качестве входных данных и реализует цель посредством двойной отправки.
Это довольно абстрактный способ сказать то, что я пытаюсь сказать выше. Обычно вы добавляете эти методы к элементам, но если вы не можете, вам нужно добавить методы к чему-то другому, и передать их для обработки. Это немного дополнительная работа, но она может стоить того, если ситуация того заслуживает.
Если вы добавите новый конкретный элемент, то все ваши классы посетителей должны будут добавить новый visit
метод для нового элемента. Если вы не используете посетителей, вам все равно придется добавить эквивалентные методы к вашему новому конкретному элементу.
Но добавить новый метод каждому посетителю может быть сложнее, чем добавить эквивалентный набор методов в новый класс элементов. Причина заключается в том, что посетителям часто приходится пересматривать древовидную структуру элементов и, возможно, при этом необходимо управлять своими собственными данными о состоянии. Добавление нового visit
метод может потребовать изменения этих данных состояния, что предполагает размышления о том, как новый метод взаимодействует с существующим visit
методы для других элементов.
Может быть проще добавить эквивалентные методы к вашему новому классу элементов, если у вас нет посетителей, потому что вам нужно будет только беспокоиться о внутреннем состоянии нового конкретного элемента, который является более связным.
Это возникло в SO вопросе совсем недавно. Процитирую себя из этого вопроса, а более конкретно обсуждения
Причина, по которой предварительное условие не меняет набор сущностей (посещаемых вами классов), заключается в том, что это заставляет вас внедрять новый VisitXYZ для каждого конкретного посетителя. Но я никогда не придавал этому большого значения, потому что вы поддерживаете персистентного посетителя, посетителя текстового поиска, посетителя печати и проверочного посетителя, и вы идете и добавляете новую сущность, для которой вы хотите реализовать все это. функциональность в любом случае. Шаблон посетителя (с общим базовым классом) просто позволяет компилятору найти те, которые вы забыли реализовать для себя.
Так что да, часто говорят, что сложно реализовать дополнительные конкретные элементы (или объекты), но, на мой взгляд, это фигня.
По сути, шаблон посетителя является своего рода манипулятором данных, он будет
- Пройдите среди элементов, следуя некоторым правилам
- Выполните некоторые вычисления и манипуляции с данными, которые предоставляют эти элементы
Одним словом, шаблон посетителя расширит функциональность системы, не затрагивая определение класса элемента.
Но значит ли это, что класс посетителя должен быть пересмотрен, если будет добавлен новый класс конкретного элемента? Я полагаю, что это зависит от того, как шаблон посетителя разработан и реализован.
Если разделить все методы посещения посетителя на функторы посещения и динамически связать их вместе, то может быть проще при расширении системы как для посетителя, так и для посетителя.
Вот реализация шаблона посетителя, которую я написал несколько лет назад, код немного стар и не очень хорошо отлажен, но как-то работает:)