Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
лабы / Лабораторная_работа_по_паттернам23.docx
Скачиваний:
0
Добавлен:
11.02.2026
Размер:
1.18 Mб
Скачать

Output.Txt: Результат выполнения

Client: Strategy is set to normal sorting.

Context: Sorting data using the strategy (not sure how it'll do it)

a,b,c,d,e

Client: Strategy is set to reverse sorting.

Context: Sorting data using the strategy (not sure how it'll do it)

e,d,c,b,a

Output.txt:

Клиент: Стратегия настроена на нормальную сортировку. Контекст: Сортировка данных с использованием стратегии (не знаю, как это будет делать)

a,b,c,d,e

Клиент: Стратегия настроена на обратную сортировку. Контекст: Сортировка данных с использованием стратегии (не знаю, как это будет делать)

e,d,c,b,a

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

Это позволяет выбирать алгоритм путем определения соответствующего класса.

Шаблон Strategy позволяет менять выбранный алгоритм независимо от объектов клиентов, которые его используют.

Проблема: по типу клиента (или по типу обрабатываемых данных) выбрать подходящий алгоритм, который следует применить.

Если используется правило, которое не подвержено изменениям, нет необходимости обращаться к шаблону «стратегия».

Решение: отделение процедуры выбора алгоритма от его реализации. Это позволяет сделать выбор на основании контекста.

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

- Конкретные классы ConcreteStrategy реализуют эти различные алгоритмы.

- Класс Context использует конкретные классы ConcreteStrategy посредством ссылки на конкретный тип абстрактного класса Strategy.

- Классы Strategy и Context взаимодействуют с целью реализации выбранного алгоритма (в некоторых случаях классу Strategy требуется посылать запросы классу Context).

- Класс Context пересылает классу Strategy запрос, поступивший от его класса клиента.

- Этот паттерн инкапсулирует семейство алгоритмов, делая их взаимозаменяемыми.

Применять его целесообразно в следующих случаях:

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

• Требуется иметь несколько разных вариантов алгоритма.

• Например, можно определить два варианта алгоритма, один из которых требует больше времени, а другой — больше памяти.

  • Кроме того, с помощью стратегии легко определить поведение класса по умолчанию.

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

  • Инкапсулированные алгоритмы можно затем применять в разных контекстах;

• В алгоритме хранятся данные, о которых клиент не должен «знать». Стратегия позволяет не раскрывать сложные, специфичные для алгоритма структуры данных;

• В классе определено много вариантов поведения, что представлено разветвленными условными операторами. В этом случае проще перенести код из ветвей в отдельные классы стратегий.

Структура паттерна приведена на рис.

Паттерн состоит из следующих классов:

Strategy (стратегия) объявляет общий для всех поддерживаемых алгоритмов интерфейс.

• Класс Context пользуется этим интерфейсом для вызова конкретного алгоритма, определенного в классе ConcreteStrategy;

ConcreteStrategy (конкретная стратегия) — наследник класса Strategy. Реализует алгоритм, использующий интерфейс, объявленный в классе Strategy;

Context (контекст) конфигурируется объектом класса ConcreteStrategy. Хранит ссылку на объект класса Strategy и может определять интерфейс, который позволяет объекту Strategy получить доступ к данным контекста.

Таким образом, объект Context делегирует реализацию конкретного алгоритма поведения объекту 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 определяет семейство алгоритмов.

- Это позволяет отказаться от использования переключателей и/или условных операторов.

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

Реализация

- Класс, который использует алгоритм (Context), включает абстрактный класс (Strategy), обладающий абстрактным методом, определяющим способ вызова алгоритма.

- Каждый производный класс реализует один требуемый вариант алгоритма.

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

Полезные сведения

И Стратегия, и Декоратор могут применяться для изменения поведения конкретных классов.

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

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

Использование

- Архитектура Microsoft WDF (Windows Driver Frameworks — набор программных инструментов, облегчающих разработку драйверов устройств для Windows) основана на этом паттерне.

- Библиотека ATL (Active Template Library — набор шаблонных классов языка C++, разработанных компанией Microsoft для упрощения написания COM-компонентов.)

В то же время ATL позволяет создавать небольшие по размеру элементы управления, которые не требуют поддержки библиотек. Библиотека содержит в себе набор классов threading model, которые являются Cтратегиями (различными реализациями Lock/Unlock (зафиксировать/отменить  /блокировать /разблокировать), которые потом используются основными классами системы).

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

#include <iostream>

class Strategy

{ public:

virtual ~Strategy() {}

virtual void use(void) = 0;

};

class Strategy_1: public Strategy

{

public:

void use(void){ std::cout << "Strategy_1" << std::endl; };

};

class Strategy_2: public Strategy

{

public:

void use(void){ std::cout << "Strategy_2" << std::endl; };

};

class Strategy_3: public Strategy

{

public:

void use(void){ std::cout << "Strategy_3" << std::endl; };

};

class Context

{ protected:

Strategy* operation;

public:

virtual ~Context() {}

virtual void useStrategy(void) = 0;

virtual void setStrategy(Strategy* v) = 0;

};

class Client: public Context

{ public: