意图
外观模式是一种结构型设计模式, 能为程序库、 框架或其他复杂类提供一个简单的接口。
问题
假设你必须在代码中使用某个复杂的库或框架中的众多对象。正常情况下,需要负责所有对象的初始化工作、管理其依赖关系并按正确的顺序执行方法等。最终,程序中类的业务逻辑将与第三方类的实现细节紧密耦合,使得理解和维护代码的工作很难进行。
解决方案
外观类为包含许多活动部件的复杂子系统提供一个简单的接口。与直接调用子系统相比,外观提供的功能可能比较有限,但它却包含了客户端真正关心的功能。
如果你的程序需要与包含几十种功能的复杂库整合,但只需使用其中非常少的功能,那么使用外观模式会非常方便。
示例代码
#include <iostream>
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* m_subsystem1;
Subsystem2* m_subsystem2;
public:
Facade(Subsystem1 *subsystem1 = nullptr,
Subsystem2 *subsystem2 = nullptr) {
this->m_subsystem1 = subsystem1 ? subsystem1 : new Subsystem1;
this->m_subsystem2 = subsystem2 ? subsystem1 : new Subsystem2;
}
~Facade() {
delete m_subsystem1;
delete m_subsystem2;
}
std::string Operation() {
std::string result = "Facade initializes subsystems:\n";
result += this->m_subsystem1->Operation1();
result += this->m_subsystem2->Operation1();
result += "Facade orders subsystems to perform the action:\n";
result += this->m_subsystem1->OperationN();
result += this->m_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;
}
外观模式结构
小结
适合应用场景
- 如果你需要一个指向复杂子系统的直接接口,且该接口的功能有限,则可以使用外观模式。
- 如果需要将子系统组织为多层结构,可以使用外观。
优点
- 可以让自己的代码独立于复杂子系统。
- 降低了大型软件系统中的编译依赖性,简化了系统在不同平台的移植过程。编译一个子系统不需要编译其他子系统;修改一个子系统不影响其他子系统;子系统内部变化也不会影响到外观对象。
缺点
- 外观可能成为与程序中所有类都耦合的上帝对象。
参考
22种设计模式:refactoringguru.cn/design-patterns
《设计模式:可复用面向对象软件的基础》