Войти
ПрограммированиеТерминыОбщее

Стратегия (Policy)

Стратегии (Policy) — это механизм обобщённого программирования, описанный Александреску в книге «Современное проектирование на C++». Кроме того, стратегии Александреску имеют много общего с паттерном Strategy.

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

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

Рассмотрим, например, реализацию умного указателя (игнорируя рекомендации использовать стандартные классы и boost ;).

Александреску предлагает в этом случае следующий набор стратегий:

  • Стратегия хранения: указывает типы собственно указателя, ссылочный тип и т. д.
  • Стратегия владения: глубокое копирование/COW/RC/...
  • Стратегия преобразования: выполняет преобразования из обычных указателей в умные и обратно.
  • Стратегия проверки: проверяет правильность инициализации и разыменования указателя.
  • (Остальные операции над умным указателем не настолько важны, по мнению Александреску, чтобы создавать для них отдельные стратегии). Это лишь пример видения проблемы; вы можете реализовать собственное видение стратегий.

    Например, дадим определение стратегии для создания объектов - Creator.
    Стратегия Creator описывает шаблонный класс типа T. Этот шаблонный класс должен предоставить функцию-член с именем

    Create, не имеющую аргументов и возвращающую указатель на объект класса T. Другими словами, каждый вызов функции Create

    должен возвращать указатель на новый объект класса T. Режим создания объекта определяется во время реализации стратегии.

    К примеру, определим три класса стратегий, реализующих стратегию Creator.
    Первый класс стратегий будет использовать оператор new.
    Второй класс стратегий будет использовать функцию malloc.
    Третий класс стратегий будет создавать объекты, клонируя их прототипы.

    Рассмотрим реализации этих классов стратегий:

    1. Используется оператор new

    template <class T>
    struct OpNewCreator
    {
        static T* Create()
        {
            return new T;
        }
    };

    2. Используется функция malloc

    template <class T>
    struct MallocCreator
    {
        static T* Create()
        {
            void *buf = std::malloc(sizeof(T));
            if (!buf) return 0;
            return new(buf) T;
        }
    };

    3. Клонируются прототипы

    template <class T>
    struct PrototypeCreator
    {
    private:
        T* pPrototype_;
    public:
        PrototypeCreator(T* pObj = 0) 
            : pPrototype_(pObj)
        {}
        T* Create()
        {
            return pPrototype_ ? pPrototype_->Clone() : 0;
        }
        T* GetPrototype() { return pPrototype_; }
        void SetPrototype(T* pObj) { pPrototype_ = pObj; }
    };

    Данная стратегия Creator может иметь сколько угодно реализаций. Эти реализации называют классами стратегий.

    После этого можно определить главный класс, который использует одну из реализаций стратегии Creator.

    template <template <class> class CreationPolicy>
    class WidgetManager : public CreationPolicy<Widget>
    {
        ...
    };

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

    typedef WidgetManager<PrototypeCreator> MyWidgetManager;
    
    ...
    
    MyWidgetManager wm;
    
    Widget *prototype = wm.GetPrototype();

    Что такое Стратегия (Policy)?

    12 декабря 2005 (Обновление: 15 мар. 2011)

    Комментарии [2]