В чем разница между паттерном стратегии и паттерном посетителя? - PullRequest
32 голосов
/ 29 декабря 2011

У меня проблемы с пониманием этих двух шаблонов проектирования.

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

Спасибо.

enter image description here

enter image description here

Ответы [ 9 ]

78 голосов
/ 04 января 2012

Вот как я на это смотрю.Шаблон стратегии похож на отношение 1: много .Когда существует один тип объекта, и я хочу применить к нему несколько операций, я использую шаблон стратегии.Например, если у меня есть класс Video, который инкапсулирует видеоклип, я могу захотеть сжать его различными способами.Поэтому я создаю группу классов стратегии:

MpegCompression
AviCompression
QuickTimeCompression

и т. Д.

Я думаю о шаблоне посетителей как многие: многие отношения.Допустим, мое приложение стало включать не только видео, но и аудиоклипы.Если я придерживаюсь шаблона стратегии, мне придется продублировать классы сжатия - один для видео и один для аудио:

MpegVideoCompression
MpegAudioCompression

и т. Д. *

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

MpegCompression::compressVideo(Video object)    
MpegCompression::compressAudio(Audio object)
11 голосов
/ 29 декабря 2011

Шаблон Стратегии используется для предоставления различных алгоритмов стандартизированному интерфейсу.Типичным примером может быть утилита сортировки, которая позволяет пользователю (программисту) выбирать между различными алгоритмами сортировки, каждый из которых вызывается через один и тот же интерфейс.

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

Возвращаясь к нашему примеру, набор алгоритмов сортировки может быть реализован либо с помощью шаблона Strategy, либо с помощью шаблона Visitor.

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

Две стороны одной монеты ...

Имеет ли это смысл?

5 голосов
/ 06 ноября 2015

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

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

Надеюсь, это поможет вам вспомнить:)

2 голосов
/ 14 ноября 2013

Определяющим отличием является то, что Посетитель предлагает другое поведение для подклассов элемента, используя перегрузку операторов.Он знает, над чем работает или посещает.

Стратегия, тем временем, будет иметь согласованный интерфейс для всех своих реализаций.

Посетитель используется, чтобы позволить частям объекта использовать согласованные средства для выполнения чего-либо.Стратегия используется, чтобы разрешить внедрение зависимости от того, как что-то сделать.

Так что это будет посетитель:

class LightToucher : IToucher{
    string Touch(Head head){return "touched my head";}
    string Touch(Stomach stomach){return "hehehe!";}
}

с другим типом

class HeavyToucher : IToucher{
   string Touch(Head head){return "I'm knocked out!";}
   string Touch(Stomach stomach){return "oooof you bastard!";}
}

У нас есть класс, который затем может использовать этого посетителя для выполнения своей работы и изменять его в зависимости от него:

class Person{
    IToucher visitor;
    Head head;
    Stomach stomach;
    public Person(IToucher toucher)
    {
          visitor = toucher;

          //assume we have head and stomach
    }

    public string Touch(bool aboveWaist)
    {
         if(aboveWaist)
         {
             visitor.Touch(head);
         }
         else
         {
             visitor.Touch(stomach);
         }
    }
}

Так что, если мы сделаем это, var person1 = new Person (new LightToucher ());var person2 = new Person (новый HeavyToucher ());

        person1.Touch(true); //touched my head
        person2.Touch(true);  //knocked me out!
1 голос
/ 10 августа 2015

Я рассматриваю шаблон стратегии как способ внедрения метода / стратегии в объект, но обычно сигнатура этого метода принимает некоторые значения параметров и возвращает результат, поэтому он не связан с пользователем стратегии: От Википедия :

class Minus : ICalculateStrategy {
    public int Calculate(int value1, int value2) {
        return value1 - value2;
    }
}

Посетитель вместо этого связывается с пользователем посредством двойной отправки и обычно сохраняет состояние. Хороший пример здесь , я просто скопирую оттуда:

public class BlisterPack
{
    // Pairs so x2
    public int TabletPairs { get; set; }
}

public class Bottle
{
    // Unsigned
    public uint Items { get; set; }
}

public class Jar
{
    // Signed
    public int Pieces { get; set; }
}

public class PillCountVisitor : IVisitor
{
    public int Count { get; private set; }

    #region IVisitor Members

    public void Visit(BlisterPack blisterPack)
    {
        Count += blisterPack.TabletPairs * 2;
    }

    public void Visit(Bottle bottle)
    {
        Count += (int) bottle.Items;
    }

    public void Visit(Jar jar)
    {
        Count += jar.Pieces;
    }

    #endregion
}

public class BlisterPack : IAcceptor
{
    public int TabletPairs { get; set; }

    #region IAcceptor Members

    public void Accept(IVisitor visitor)
    {
        visitor.Visit(this);
    }

    #endregion
}

Как видно, у посетителя есть состояние (public int Count), и он работает со списком известных типов BlisterPack, Bottle, Jar. Поэтому, если вы хотите поддерживать новый тип, вам нужно изменить всех посетителей, добавив этот тип.

Также он связан с типами, с которыми работает, из-за "visitor.Visit ( this );". Что произойдет, если я уберу или изменю бутылку со свойством «Предметы»? ... все посетители потерпят неудачу.

0 голосов
/ 25 июля 2018

Я постараюсь сделать кратчайший ответ.

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

0 голосов
/ 29 декабря 2017

Если у вас есть только один единственный контекст или элемент, и вам нужно выполнить различные операции с этим контекстом, тогда вы можете выбрать Strategy Pattern.Это 1:M relationship, упомянутый в ответе выше.java.util.Comparator является хорошим примером шаблона проектирования Стратегии в действии.Там мы можем иметь разные стратегии сортировки для одной и той же коллекции (контекст или элемент).

С другой стороны, скажем, что у вас есть несколько элементов, все они соответствуют общему контракту и должны выполнять различные операции с каждым из них.В качестве примера рассмотрим вариант использования автомойки, где у вас есть кузов, двигатель, колесо и т. Д. И каждый из которых можно мыть с помощью пара или воды.Это хорошее использование Visitor Pattern.Но убедитесь, что ваши элементы контекста остаются неизменными и никогда не меняются.Если элементы собираются изменить, скажем, добавив элемент Door к Car, то вам нужно изменить всех Посетителей, добавив один новый метод в каждый из них и нарушив OCP характер шаблона.Итак, это отношение M:N, указанное в приведенном выше ответе.

Если вам интересно узнать больше о тонких различиях между двумя Design Patterns, я предлагаю вам прочитать эту статью .

0 голосов
/ 14 ноября 2014

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

0 голосов
/ 29 декабря 2011

Их различия:

  1. Мотивация
  2. Намерение
  3. Реализация

Не уверен, что получается при сравнении двух разных вещейно сравните Стратегия с Посетитель .

Что в этих двух одинаковых, чтобы взглянуть на их различия?

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