Паттерн Фасад на C++
Фасад – это структурный паттерн, который предоставляет простой (но урезанный) интерфейс к сложной системе объектов, библиотеке или фреймворку.
Кроме того, что Фасад позволяет снизить общую сложность программы, он также помогает вынести код, зависимый от внешней системы в единственное место.
Особенности паттерна на C++
Сложность:
Популярность:
Применимость: Паттерн часто встречается в клиентских приложениях, написанных на C++, которые используют классы-фасады для упрощения работы со сложными библиотеки или API.
Признаки применения паттерна: Фасад угадывается в классе, который имеет простой интерфейс, но делегирует основную часть работы другим классам. Чаще всего, фасады сами следят за жизненным циклом объектов сложной системы.
Концептуальный пример
Этот пример показывает структуру паттерна Фасад, а именно – из каких классов он состоит, какие роли эти классы выполняют и как они взаимодействуют друг с другом.
main.cc: Пример структуры паттерна
/**
* Подсистема может принимать запросы либо от фасада, либо от клиента напрямую.
* В любом случае для Подсистемы Фасад – это еще один клиент, и он не является
* частью Подсистемы.
*/
class Subsystem1 {
public:
std::string Operation1() const {
return "Subsystem1: Ready!\n";
}
// ...
std::string OperationN() const {
return "Subsystem1: Go!\n";
}
};
/**
* Некоторые фасады могут работать с разными подсистемами одновременно.
*/
class Subsystem2 {
public:
std::string Operation1() const {
return "Subsystem2: Get ready!\n";
}
// ...
std::string OperationZ() const {
return "Subsystem2: Fire!\n";
}
};
/**
* Класс Фасада предоставляет простой интерфейс для сложной логики одной или
* нескольких подсистем. Фасад делегирует запросы клиентов соответствующим
* объектам внутри подсистемы. Фасад также отвечает за управление их жизненным
* циклом. Все это защищает клиента от нежелательной сложности подсистемы.
*/
class Facade {
protected:
Subsystem1 *subsystem1_;
Subsystem2 *subsystem2_;
/**
* В зависимости от потребностей вашего приложения вы можете предоставить
* Фасаду существующие объекты подсистемы или заставить Фасад создать их
* самостоятельно.
*/
public:
/**
* В этому случае мы делегируем владение памятью классу Facade
*/
Facade(
Subsystem1 *subsystem1 = nullptr,
Subsystem2 *subsystem2 = nullptr) {
this->subsystem1_ = subsystem1 ?: new Subsystem1;
this->subsystem2_ = subsystem2 ?: new Subsystem2;
}
~Facade() {
delete subsystem1_;
delete subsystem2_;
}
/**
* Методы Фасада удобны для быстрого доступа к сложной функциональности
* подсистем. Однако клиенты получают только часть возможностей подсистемы.
*/
std::string Operation() {
std::string result = "Facade initializes subsystems:\n";
result += this->subsystem1_->Operation1();
result += this->subsystem2_->Operation1();
result += "Facade orders subsystems to perform the action:\n";
result += this->subsystem1_->OperationN();
result += this->subsystem2_->OperationZ();
return result;
}
};
/**
* Клиентский код работает со сложными подсистемами через простой интерфейс,
* предоставляемый Фасадом. Когда фасад управляет жизненным циклом подсистемы,
* клиент может даже не знать о существовании подсистемы. Такой подход позволяет
* держать сложность под контролем.
*/
void ClientCode(Facade *facade) {
// ...
std::cout << facade->Operation();
// ...
}
/**
* В клиентском коде могут быть уже созданы некоторые объекты подсистемы. В этом
* случае может оказаться целесообразным инициализировать Фасад с этими
* объектами вместо того, чтобы позволить Фасаду создавать новые экземпляры.
*/
int main() {
Subsystem1 *subsystem1 = new Subsystem1;
Subsystem2 *subsystem2 = new Subsystem2;
Facade *facade = new Facade(subsystem1, subsystem2);
ClientCode(facade);
delete facade;
return 0;
}
Output.txt: Результат выполнения
Facade initializes subsystems:
Subsystem1: Ready!
Subsystem2: Get ready!
Facade orders subsystems to perform the action:
Subsystem1: Go!
Subsystem2: Fire!