Декоратор — структурный шаблон проектирования, предназначенный для динамического подключения дополнительного поведения к объекту

Шаблон Декоратор предоставляет гибкую альтернативу практике создания подклассов с целью расширения функциональности.

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

Решение: шаблон “декоратор” предусматривает расширение функциональности объекта без определения подклассов.

 

Класс ConcreteComponent — класс, в который с помощью шаблона Декоратор добавляется новая функциональность.

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

Абстрактный класс Component определяет интерфейс для использования всех этих классов.

Пример реализации шаблона:

 

#include <iostream>

#include <memory>

 

class IComponent {

public:

    virtual void operation() = 0;

   virtual ~IComponent(){}

};

 

class Component: public IComponent {

public:

    virtual void operation() {

              std::cout<<"World!"<<std::endl;

    }

};

 

class DecoratorOne: public IComponent {

    std::shared_ptr<IComponent> m_component;

 

public:

    DecoratorOne(IComponent* component): m_component(component) {}

 

    virtual void operation() {

              std::cout << ", ";

              m_component->operation();

    }

};

 

class DecoratorTwo: public IComponent {

    std::shared_ptr<IComponent> m_component;

 

public:

    DecoratorTwo(IComponent* component): m_component(component) {}

 

    virtual void operation() {

              std::cout << "Hello";

              m_component->operation();

    }

};

 

int main() {

    DecoratorTwo obj(new DecoratorOne(new Component()));

    obj.operation(); // prints "Hello, World!\n"

 

    return 0;

}

Порождающие шаблоны

Абстрактная фабрика (Abstract Factory)

Абстрактная фабрикапорождающий шаблон проектирования, позволяющий изменять поведение системы, варьируя создаваемые объекты, при этом сохраняя интерфейсы.

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

общее поведение.

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

Затем пишутся классы, реализующие этот интерфейс.

Этот шаблон предоставляет интерфейс для создания семейств взаимосвязанных или взаимозависимых объектов, не специфицируя их конкретных классов.

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

Фабрика, которая выпускает, например, мебель, не может производить, например, еще и компоненты для смартфонов.

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

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

Паттерн предоставляет интерфейс для создания семейств, связанных между собой, или независимых объектов, конкретные классы которых неизвестны.

От класса «абстрактная фабрика» наследуются классы конкретных фабрик, которые содержат методы создания конкретных объектов-продуктов, являющихся наследниками класса «абстрактный продукт», объявляющего интерфейс для их создания.

 Клиент пользуется только интерфейсами, заданными в классах «абстрактная фабрика» и «абстрактный продукт».

 

 

 

 

Реализация на C++

//общий интерфейс для данных любого формата

class FormattedData {

//...

};

//конкретный формат

class FormattedData1: public FormattedData {

//...

};

//другой конкретный формат

class FormattedData2: public FormattedData {

//...

};

//абстрактная фабрика

class AbstractFactory {

public:

virtual FormattedData* createFormattedData() = 0;

};

//фабрика для создания объектов, содержащих данные

//нужного формата

class FormatFactory: public AbstractFactory {

public:

FormattedData* createFormattedData() {

if(/* some condition */) {

    return new FormattedData1();

}

else {

    return new FormattedData2();

}

}

};

//использование абстрактной фабрики

int main() {

FormatFactory* pfactory = new FormatFactory();

FormattedData* pdata = pfactory->createFormattedData();

//send data

//...

if(pfactory)delete pfactory;

if(pdata)delete pdata;

return 0;}

Еще пример

#include <iostream> #include <vector> // Абстрактные базовые классы всех возможных видов воинов class Infantryman   //пехотинец { public: virtual void info() = 0; virtual ~Infantryman() {} }; class Archer    //стрелок, лучник { public: virtual void info() = 0; virtual ~Archer() {} }; class Horseman //кавалерист { public: virtual void info() = 0; virtual ~Horseman() {} }; // Конкретные классы всех видов воинов Римской армии class RomanInfantryman: public Infantryman { public: void info() { cout << "RomanInfantryman" << endl; } }; class RomanArcher: public Archer { public: void info() { cout << "RomanArcher" << endl; } }; class RomanHorseman: public Horseman { public: void info() { cout << "RomanHorseman" << endl; } }; // Классы всех видов воинов армии Карфагена class CarthaginianInfantryman: public Infantryman { public: void info() { cout << "CarthaginianInfantryman" << endl; } }; class CarthaginianArcher: public Archer { public: void info() { cout << "CarthaginianArcher" << endl; } }; class CarthaginianHorseman: public Horseman { public: void info() { cout << "CarthaginianHorseman" << endl; } }; // Абстрактная фабрика для производства воинов class ArmyFactory { public: virtual Infantryman* createInfantryman() = 0; virtual Archer* createArcher() = 0; virtual Horseman* createHorseman() = 0; virtual ~ArmyFactory() {} }; // Фабрика для создания воинов Римской армии class RomanArmyFactory: public ArmyFactory { public: Infantryman* createInfantryman() { return new RomanInfantryman; } Archer* createArcher() { return new RomanArcher; } Horseman* createHorseman() { return new RomanHorseman; } }; // Фабрика для создания воинов армии Карфагена class CarthaginianArmyFactory: public ArmyFactory { public: Infantryman* createInfantryman() { return new CarthaginianInfantryman; } Archer* createArcher() { return new CarthaginianArcher; } Horseman* createHorseman() { return new CarthaginianHorseman; } }; // Класс, содержащий всех воинов той или иной армии class Army { public: ~Army() { int i; for(i=0; i<vi.size(); ++i) delete vi[i]; for(i=0; i<va.size(); ++i) delete va[i]; for(i=0; i<vh.size(); ++i) delete vh[i]; } void info() { int i; for(i=0; i<vi.size(); ++i) vi[i]->info(); for(i=0; i<va.size(); ++i) va[i]->info(); for(i=0; i<vh.size(); ++i) vh[i]->info(); } vector<Infantryman*> vi; vector<Archer*> va; vector<Horseman*> vh; }; // Здесь создается армия той или иной стороны class Game { public: Army* createArmy(ArmyFactory& factory) { Army* p = new Army; p->vi.push_back(factory.createInfantryman()); p->va.push_back(factory.createArcher()); p->vh.push_back(factory.createHorseman()); return p; } }; int main() { Game game; RomanArmyFactory ra_factory; CarthaginianArmyFactory ca_factory; Army * ra = game.createArmy(ra_factory); Army * ca = game.createArmy(ca_factory); cout << "Roman army:" << endl; ra->info(); cout << "\nCarthaginian army:" << endl; ca->info(); //... }

Вывод программы будет следующим:

  Roman army: RomanInfantryman RomanArcher RomanHorseman Carthaginian army: CarthaginianInfantryman CarthaginianArcher CarthaginianHorseman  

Для данного паттерна так же подходит другое название — виртуальный конструктор.


Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: