[Moscow.pm] Strategy ("Стратегия") и "Декоратор"(Decorator/Wrapper) реализация на Perl

Ruslan Zakirov ruz на bestpractical.com
Ср Июл 9 14:09:07 PDT 2008


Реализация декоратора в SVK:
http://code.bestpractical.com/svk/trunk/lib/SVK/Editor/ByPass.pm

В accessor _editor кладется следующий по ходу редактор. Декораторы
наследуются от SVK::Editor::ByPass. Терминальные редакторы от
SVK::Editor (аля ConcreteComponents). Таким образом можно выстраивать
цепочки редактирования.

Делигирование при отсутствии локальной реализации сделано через
AUTOLOAD, что позволяет свободно менять базовый интерфейс без
изменения SVK::Editor::ByPass.

Вполне себе живет, можно улучшить.

2008/7/9 Orlovsky Alexander <nordicdyno на yandex.ru>:
> Итак, первыми паттернами для реализации я выбрал родственные шаблоны Strategy ("Стратегия") и "Декоратор"(Decorator/Wrapper).
> В начале немного теории. (Не забываем про поисковики :)
>
> Несмотря на то, что "Декоратор" и "Стратегия" в GoF-буке находятся в разных разделах ("Структурные паттерны" и "Паттерны поведения" соответственно), эти паттерны решают похожие задачи. Оба могут удалять условную логику и оба делают это, перемещая такое поведение в один или несколько новых классов вне рамок существующего класса.
>
> Различие заключается в способе использования этих новых классов.
>
> Декораторы (их экземпляры) представляют собой оболочки вокруг объекта (или друг друга), в то время, как один или несколько экземпляров стратегии  используются внутри объекта.
>
> Декораторы несколько более тяжеловесны, т.к. базовые классы в общем случае не могут разделять их объекты (в отличие от стратегий).
>
> Интерфейс стратегии может быть произвольным, в отличие от интерфейса декоратора. Класс декоратора должен реализовывать те же методы, что и классы которые он декорирует (имеет общий с ними интерфейс).
>
> Классы, вокруг которых оборачивается декоратор, ничего не знают о нем, но если мы используем шаблон стратегии, то класс знает о существовании объектов стратегий и должен уметь их использовать.
>
> Внутри классов, содержащих много данных и реализующих много открытых методов, традиционно используют одну или несколько стратегий.
>
> ------------------------------------------------------------------------------------
> 1) "Декоратор":
>
> Дополнительная информация, а также UML-схема примера реализации:
> http://codelab.ru/pattern/decorator/
> http://en.wikipedia.org/wiki/Decorator_pattern
>
> Пример кода: http://paste.org/index.php?id=3271
>
> Комментарий к коду:
>
> В коде реализованы два "компонента": SimpleArrayPrinter, PrettyArrayPrinter, наследующих от общего предка ArrayPrinter.
> ArrayPrinter служит аналогом абстрактного класса "Component" в схеме из [1]  (см. также ссылки выше).
>
> SimpleArrayPrinter, PrettyArrayPrinter -- это реализации "ConcreteComponent".
> SimpleArrayPrinter -- выводит матрицу на экран практически без какого-либо оформления. (не считая разделитель)
> PrettyArrayPrinter -- выводит матрицу с помощью CPAN-модуля Pretty::Table (это сделано для простоты и наглядности, в реальном декораторе, скорее всего содержалась бы больше логики оформления)
>
> Decorator -- аналог абстрактного класса "Decorator" [1], от него наследуются два подкласса декораторов (на схеме это "ConcreteDecorator"-ы)
> c именами: VerticalDecorator, ReverseDecorator.
> Класс Decorator, в свою очередь, наследует от ArrayPrinter, т.к. должен реализовывать общий с ним интерфейс (чтобы быть прозрачным для
>
> клиента и других декораторов в цепочке).
>
> VerticalDecorator -- "переворчивает" матрицу на 90%
> ReverseDecorator  -- обращает списки элементов в каждой из строк.
>
> На примере можно убедиться, что можно оборачивать любой из объектов семейства ArrayPrinter декораторами в любой последовательности.
>
> Попробуйте поменять местами вызов декораторов, а также подставить вместо "PrettyArrayPrinter->new(" строку "SimpleArrayPrinter->new(".
> Также можно убрать какой-либо декоратор из цепочки (либо убрать все декораторы вовсе), после чего увидеть как измененилось поведение объекта.
>
> Можно отметить, что конструктор декоратора помимо декорируемого объекта может принимать и дополнительные параметры, которые могут менять его поведение.
>
> ( см. также Class::Decorator на CPAN )
>
> ------------------------------------------------------------------------------------
> 1) "Стратегия":
>
>  Шаблон "Стратегия" обычно применяют как способ для исключения условной логики.
>
> Дополнительная информация, а также UML-схема примера реализации:
> http://codelab.ru/pattern/strategy/
> http://en.wikipedia.org/wiki/Strategy_pattern
>
> Пример кода: http://paste.org/index.php?id=3272
>
> Комментарии к коду:
> Вообще код достаточно простой и не нуждается в дополнительных комментариях.
>
> Замечу, что можно реализовать паттерн стратегия и не используя классы стратегий ("ConcreteStartegy").
> Вместо ссылки на объект, можно ссылку на функцию, нужным образом обрабатывающую данные.
> Это также будет шаблон "Стратегия". Объекты конкретных стратегий могут понадобится при достаточно сложном внутреннем устройстве реализации стратегии. (к сожалению затрудняюсь привести хороший пример, может быть подписчики помогут?)
> ---------------------------------------------------------
>
> Литература:
> [1] "Приемы объектно-ориентированного проектирования. Паттерны проектирования." Гамма, Хели, Джонсон, Влиссидес
> [2] "Рефакторинг с использованием шаблонов" Д. Кириевски
> [3] "Рефакторинг" Фаулер
> --
> Moscow.pm mailing list
> moscow-pm на pm.org | http://moscow.pm.org
>



-- 
Best regards, Ruslan.


Подробная информация о списке рассылки Moscow-pm