feat: Add Facade

Implemented a demo for the Facade.
This commit is contained in:
Yuki 2025-04-12 03:55:21 +08:00
parent 9f29b7a6ff
commit 596204675b
Signed by: yuki
GPG Key ID: CF40579331C06C73
2 changed files with 72 additions and 0 deletions

66
11_facade.cpp Normal file
View File

@ -0,0 +1,66 @@
#include <iostream>
#include <memory>
using namespace std;
class Projector {
int brightness;
public:
void set_brightness(int brightness) { this->brightness = brightness; }
int get_brightness() { return brightness; }
};
class Amplifier {
int volume;
string mode;
public:
Amplifier() : mode("Normal") {}
void set_volume(int volume) { this->volume = volume; }
int get_volumn() { return volume; }
void set_mode(const string& mode) { this->mode = mode; }
const string& get_mode() {return this->mode; }
};
class Player {
unique_ptr<Projector> pro;
unique_ptr<Amplifier> amp;
public:
Player(unique_ptr<Projector> p, unique_ptr<Amplifier> a) :
pro(move(p)), amp(move(a)) {}
void play(const string& movie) {
cout << "Play movie: " << movie
<< " brightness: " << pro->get_brightness()
<< " volume: " << amp->get_volumn()
<< " in " << amp->get_mode() << " mode." << endl;
}
};
class TheaterFacade {
public:
void play(const string& movie) {
auto pro = make_unique<Projector>();
auto amp = make_unique<Amplifier>();
pro->set_brightness(10);
amp->set_volume(10);
Player p(move(pro), move(amp));
p.play(movie);
}
};
int main() {
// Simply use without configure
TheaterFacade f;
f.play("CSAPP");
// You can still control the details
auto pro = make_unique<Projector>();
auto amp = make_unique<Amplifier>();
pro->set_brightness(20);
amp->set_volume(42);
amp->set_mode("Virtual Surround");
Player p(move(pro), move(amp));
p.play("CSAPP");
}

View File

@ -71,3 +71,9 @@
有时,我们需要给动态的一个类添加一些组件。例如:对于制作一杯咖啡,可以添加牛奶,糖等。一种做法是使用继承,这显然会造成类爆炸。另一种做法是将这些配料抽象成一个类,咖啡类维护一个配料的列表。对于纯数据,如计算最终价格,这样是合理的。但是对于添加额外行为,这就会将逻辑集中到 Coffee 类中。例如希望添加牛奶时咖啡必须加热,就不得不修改 Coffee 类,在它的 make 函数中添加处理逻辑。
装饰器模式解决了这个问题。让所有的配料都继承自 Coffee构建时则额外需要一个被装饰对象的指针构造函数中还能插入额外的处理。这样可以让每一层都能主动拦截、加工、改写行为而不需要集中到一个地方。对于客户端代码来说装饰器和原对象是一样的。当需要对咖啡做某个动作时可以对装饰器做装饰器再调用被修饰对象指针的对应动作。由于包含关系装饰器还天然记录了顺序。
## 外观模式Facade
在一个复杂系统中,往往由多个子系统协同工作来完成一项功能。例如,一个编译器可能包含词法分析器、语法分析器、语义分析器、优化器和代码生成器等多个模块。如果每次都要让调用者直接与这些子系统交互,不仅复杂、容易出错,而且对用户也不友好。而实际上,许多操作是常用的、固定的组合,例如“编译整个程序”就总是涉及所有子模块的调用顺序。
很容易想到通过一个统一的入口,也就是新增一个“外观类”或“外观函数”,封装这些子系统的内部调用逻辑。这就是外观模式,对外提供一个简化接口,同时又保留了对细节的操控能力。