Facade 패턴
의도
퍼사드 패턴은 라이브러리에 대한, 프레임워크에 대한 또는 다른 클래스들의 복잡한 집합에 대한 단순화된 인터페이스를 제공하는 구조적 디자인 패턴입니다.

문제
정교한 라이브러리나 프레임워크에 속하는 광범위한 객체들의 집합으로 당신의 코드를 작동하게 만들어야 한다고 상상해 봅시다. 일반적으로, 당신은 이러한 객체들을 모두 초기화하고, 종속성 관계들을 추적하고, 올바른 순서로 메서드들을 실행하는 등의 작업을 수행해야 합니다.
그 결과 당신의 클래스들의 비즈니스 로직이 타사 클래스들의 구현 세부 사항들과 밀접하게 결합하여 코드를 이해하고 유지 관리하기가 어려워집니다.
해결책
퍼사드는 움직이는 부분이 많이 포함된 복잡한 하위 시스템에 대한 간단한 인터페이스를 제공하는 클래스입니다. 하위 시스템과 직접 작업하는 것과 비교하면 퍼사드는 제한된 기능성을 제공합니다. 하지만 퍼사드에는 클라이언트들이 정말로 중요하게 생각하는 기능들만 포함됩니다.
퍼사드는 당신의 앱을 수십 가지의 기능이 있는 정교한 라이브러리와 통합해야 하지만 그 기능의 극히 일부만을 필요로 할 때 편리합니다.
예를 들어, 고양이가 나오는 짤막하고 재미있는 영상을 소셜 미디어에 올리는 어떤 앱은 전문적인 비디오 변환 라이브러리를 사용할 수 있습니다. 그러나 이 앱이 이 라이브러리로부터 필요로 하는 것은 encode(filename, format) 단일 메서드가 있는 클래스뿐입니다. 이러한 클래스를 만든 후 비디오 변환 라이브러리와 연결하면 당신은 당신의 첫 번째 퍼사드를 소유하게 됩니다.
실제상황 적용

전화로 주문하기.
전화로 주문하기 위해 매장에 전화를 걸었을 때 전화를 받는 교환원이 바로 상점의 모든 서비스와 부서에 대한 당신의 퍼사드입니다. 이때 교환원은 주문 시스템, 지불 게이트웨이 및 다양한 배송 서비스에 대한 간단한 음성 인터페이스를 제공합니다.
/**
* The Subsystem can accept requests either from the facade or client directly.
* In any case, to the Subsystem, the Facade is yet another client, and it's not
* a part of the Subsystem.
*/
class Subsystem1 {
public:
std::string Operation1() const {
return "Subsystem1: Ready!\n";
}
// ...
std::string OperationN() const {
return "Subsystem1: Go!\n";
}
};
/**
* Some facades can work with multiple subsystems at the same time.
*/
class Subsystem2 {
public:
std::string Operation1() const {
return "Subsystem2: Get ready!\n";
}
// ...
std::string OperationZ() const {
return "Subsystem2: Fire!\n";
}
};
/**
* The Facade class provides a simple interface to the complex logic of one or
* several subsystems. The Facade delegates the client requests to the
* appropriate objects within the subsystem. The Facade is also responsible for
* managing their lifecycle. All of this shields the client from the undesired
* complexity of the subsystem.
*/
class Facade {
protected:
Subsystem1 *subsystem1_;
Subsystem2 *subsystem2_;
/**
* Depending on your application's needs, you can provide the Facade with
* existing subsystem objects or force the Facade to create them on its own.
*/
public:
/**
* In this case we will delegate the memory ownership to Facade Class
*/
Facade(
Subsystem1 *subsystem1 = nullptr,
Subsystem2 *subsystem2 = nullptr) {
this->subsystem1_ = subsystem1 ?: new Subsystem1;
this->subsystem2_ = subsystem2 ?: new Subsystem2;
}
~Facade() {
delete subsystem1_;
delete subsystem2_;
}
/**
* The Facade's methods are convenient shortcuts to the sophisticated
* functionality of the subsystems. However, clients get only to a fraction of
* a subsystem's capabilities.
*/
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;
}
};
/**
* The client code works with complex subsystems through a simple interface
* provided by the Facade. When a facade manages the lifecycle of the subsystem,
* the client might not even know about the existence of the subsystem. This
* approach lets you keep the complexity under control.
*/
void ClientCode(Facade *facade) {
// ...
std::cout << facade->Operation();
// ...
}
/**
* The client code may have some of the subsystem's objects already created. In
* this case, it might be worthwhile to initialize the Facade with these objects
* instead of letting the Facade create new instances.
*/
int main() {
Subsystem1 *subsystem1 = new Subsystem1;
Subsystem2 *subsystem2 = new Subsystem2;
Facade *facade = new Facade(subsystem1, subsystem2);
ClientCode(facade);
delete facade;
return 0;
}