Шаблон посетителя и свободный синтаксис в стиле LINQ для API обхода дерева - PullRequest
2 голосов
/ 28 мая 2011

Я думаю о рефакторинге проекта с открытым исходным кодом, Afterthought , чтобы сделать его более интуитивно понятным в использовании. Основная идея заключается в том, что разработчики, создающие поправки в Afterthought, будут вносить изменения в конкретный тип .NET и получат возможность изменять сам тип, а также списки свойств, методов, событий, конструкторов и т. Д. (Дерево). API, которые я использую для внутреннего использования Метаданные Microsoft CCI , широко используют шаблон посетителей в своих API, поэтому я применил аналогичный подход в Afterthought, как показано ниже:

public override void Amend()
{
    // Amend the type here, add properties, add methods, etc.
}

public override void Amend<TProperty>(Property<TProperty> property)
{
    // Amend properties here
    if (property.Name == "Result")
    {
        // Modify Result property
    }
}

public override void Amend(Method method)
{
    // Amend methods here
    if (method.Name == "Add")
    {
        // Modify Add method
        method.Implement(TInstance instance, int x, int y) => x + y);
    }
}

Однако я обнаружил, что шаблон посетителя действительно в итоге перераспределяет код, решающий целевую проблему (например, инструментарий библиотеки классов), в серию различных методов, ориентированных на аспекты дерева. Это легко реализовать для разработчика, создающего API, но потребитель должен распространять свой код несколько неестественным образом. Поэтому я задаю вопрос: каковы преимущества использования vistor-pattern по сравнению с простым представлением дерева в виде списков и использованием подхода в стиле LINQ?

Вот альтернативный синтаксис, который я рассматриваю:

public override void Amend()
{
    // Do everything here, possibly calling methods just to organize the code

    // Modify Add method
    Methods.Named("Add").WithParams<int, int>()
        .Implement((instance, x, y) => x + y);
}

Таким образом, в этом случае автор поправки может написать весь код в одном месте (или местах по своему выбору), взаимодействуя со списками, которые предоставляют свободный / LINQ API вместо переопределяющих методов. Очевидно, что этот подход несколько менее эффективен (больше итераций и т. Д.), Но каковы его недостатки, помимо этого?

1 Ответ

3 голосов
/ 28 мая 2011

Шаблон Visitor помогает избежать создания операторов if или switch, которые будут проверять тип посещаемого элемента.Избегание этих заявлений обычно считается хорошей практикой.Если выполняемая вами операция не различает различные возможные типы элементов, которые можно посетить, то да, шаблон посетителя не дает вам никаких преимуществ по сравнению с вашим альтернативным подходом любым другим подходом.

Проблема, возможно, заключается в понимании шаблона посетителя: речь идет в основном о реализации двойной диспетчеризации на языках, которые не предоставляют эту функцию, или (в случае C #), где использование дваждыотправка приносит значительные проблемы с производительностью.Это не про обход деревьев.Это может даже использоваться для классов, которые не формируют иерархическую структуру.В книге GoF говорится, что алгоритм обхода может быть реализован либо самим посетителем, либо посещенными элементами, либо даже клиентом.

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

...