Паттерн Strategy (стратегия)

Назначение паттерна Strategy

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

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

Представленному подходу свойственны следующие недостатки:

  1. Реализация алгоритма жестко привязана к его подклассу, что затрудняет поддержку и расширение такой системы.
  2. Система, построенная на основе наследования, является статичной. Заменить один алгоритм на другой в ходе выполнения программы уже невозможно.

Применение паттерна Strategy позволяет устранить указанные недостатки.

Описание паттерна Strategy

Паттерн Strategy переносит в отдельную иерархию классов все детали, связанные с реализацией алгоритмов. Для случая программы сжатия файлов абстрактный базовый класс Compression этой иерархии объявляет интерфейс, общий для всех алгоритмов и используемый классом Compressor. Подклассы ZIP_Compression, ARJ_Compression и RAR_Compression его реализуют в соответствии с тем или иным алгоритмом. Класс Compressor содержит указатель на объект абстрактного типа Compression и предназначен для переадресации пользовательских запросов конкретному алгоритму. Для замены одного алгоритма другим достаточно перенастроить этот указатель на объект нужного типа.

Структура паттерна Strategy

UML-диаграмма классов паттерна Strategy

Реализация паттерна Strategy

Приведем реализацию приложения для сжатия файлов, спроектированного с применением паттерна Strategy.

#include <iostream>
#include <string>

// Иерархия классов, определяющая алгоритмы сжатия файлов
class Compression
{
  public:    
    virtual ~Compression() {}
    virtual void compress( const string & file ) = 0;
};

class ZIP_Compression : public Compression
{
  public:
    void compress( const string & file ) {
        cout << "ZIP compression" << endl;
    }
};

class ARJ_Compression : public Compression
{
  public:
    void compress( const string & file ) {
        cout << "ARJ compression" << endl;
    }
};

class RAR_Compression : public Compression
{
  public:
    void compress( const string & file ) {
        cout << "RAR compression" << endl;
    }
};


// Класс для использования
class Compressor 
{
  public:
    Compressor( Compression* comp): p(comp) {}
   ~Compressor() { delete p; }
    void compress( const string & file ) {
      p->compress( file);
    }
  private:
    Compression* p;
};


int main()
{
  Compressor* p = new Compressor( new ZIP_Compression);
  p->compress( "file.txt");
  delete p;
  return 0;
}

Результаты применения паттерна Strategy

Достоинства паттерна Strategy

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

Недостатки паттерна Strategy

  • Для правильной настройки системы пользователь должен знать об особенностях всех алгоритмов.
  • Число классов в системе, построенной с применением паттерна Strategy, возрастает.

results matching ""

    No results matching ""