我已经检查了维基百科文章,它似乎缺少代码示例的 c++ 版本。没有这个,我无法完全理解 Facade 模式,你能帮我用 C++ 解释一下吗?
6 回答
外观模式:为复杂的子系统或一组接口提供统一的简化接口。它提供了一个更高级别的接口,同时将客户端与复杂的子系统解耦。
一个帮助你理解的例子..出租车司机。您告诉出租车司机“带我去 PointX”(统一简化的高级界面),然后他开始执行一系列操作(转动钥匙、换档、踩油门等)来执行任务。他抽象出底层子系统(变速箱、发动机等)的复杂性,这样您就不必担心它们。驾驶员还将您与实际使用的车辆分离……您不直接与汽车交互。您可能会给他一个 Merc,但您与 Driver 的界面仍然是 TakeMeTo( X ).. 您不受任何特定型号/制造的汽车的束缚。
在现实世界的示例中,您会发现与第三方组件或库交互的外观。您不希望您的代码依赖于特定的供应商,因此您引入了一个外观接口来解耦。您还将简化此接口,例如,您的外观接口将有一个名为 SendData(string) 的方法,但在内部,实现可能会按特定顺序调用 m 个子包上的 n 个方法来完成任务。这就是维基百科页面上的图表显示的内容。
例如,将示例翻译成 C++ 并保持小
sResource = LWCPPSimple::get("http://www.perl.org")
这里虚构的 C++ 中的 WWW 库是一个外观,它统一了问题的协议、网络和解析方面,因此我可以专注于获取资源的主要焦点。get 方法将 HTTP、FTP 和其他各种协议、请求-响应、连接管理等的复杂性(在某些情况下甚至是丑陋的)隐藏/封装/保持在一个位置。此外,如果明天 LWCPPSimple 的创建者找到一个使 get() 速度提高一倍的方法,我免费获得了性能优势。我的客户代码不必更改。
class Engine
{
public:
void Start() { }
};
class Headlights
{
public:
void TurnOn() { }
};
// That's your facade.
class Car
{
private:
Engine engine;
Headlights headlights;
public:
void TurnIgnitionKeyOn()
{
headlights.TurnOn();
engine.Start();
}
};
int Main(int argc, char *argv[])
{
// Consuming facade.
Car car;
car.TurnIgnitionKeyOn();
return 0;
}
我已经对 C# 示例进行了搜索和替换。这可能对您没有帮助,因为如果您了解 C++,那么您应该能够理解 C#,因为它使用相同的构造和关键字(类、函数、命名空间、公共等)
// "Subsystem ClassA"
#include <iostream>
class SubSystemOne
{
public:
void MethodOne()
{
std::cout << " SubSystemOne Method" << std::endl;
}
}
// Subsystem ClassB"
class SubSystemTwo
{
public:
void MethodTwo()
{
std::cout << " SubSystemTwo Method" << std::endl;
}
}
// Subsystem ClassC"
class SubSystemThree
{
public:
void MethodThree()
{
std::cout << " SubSystemThree Method" << std::endl;
}
}
// Subsystem ClassD"
class SubSystemFour
{
public:
void MethodFour()
{
std::cout << " SubSystemFour Method" << std::endl;
}
}
// "Facade"
class Facade
{
SubSystemOne one;
SubSystemTwo two;
SubSystemThree three;
SubSystemFour four;
public:
Facade()
{
}
void MethodA()
{
std::cout << "\nMethodA() ---- " << std::endl;
one.MethodOne();
two.MethodTwo();
four.MethodFour();
}
void MethodB()
{
std::cout << "\nMethodB() ---- " << std::endl;
two.MethodTwo();
three.MethodThree();
}
}
int Main()
{
Facade facade = new Facade();
facade.MethodA();
facade.MethodB();
return 0;
}
从某种意义上说,Facade 只是一个 API,供想要与隐藏的东西交互的客户端使用。
当为用 C++ 实现或比 API 更复杂的东西公开简单的 C API 时,Facade 很有用。或者当库需要经过多次迭代更新并且您希望尽可能少地影响客户端时,在客户端和库之间获得一个固定的障碍。例如,如果基于 C 的库需要在内部更新为 C++ 或其他东西,或者只是换成完全不同的东西,那么 Facade 对客户端来说是一个很好的中间层。
class A {
private B b; // Class A uses Class B, the "interface"
public int f() { return b.g(); }
};
class B {
private C c; // class B uses class C, a "subsystem"
private ... ...; // other subsystems can be added
public int g() { c.h(); return c.i(); }
};
class C { // a subsystem
public void h() { ... }
public int i() { return x; }
};
A 类不会直接使用任何方法或直接影响 C 类或 B 类包含的任何其他子系统的状态。这里只显示一个子系统,因为有多少子系统并不重要。