From 596204675b9d06927a82948f87fb1734951925df Mon Sep 17 00:00:00 2001 From: Yuki Date: Sat, 12 Apr 2025 03:55:21 +0800 Subject: [PATCH] feat: Add Facade Implemented a demo for the Facade. --- 11_facade.cpp | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++ notes.md | 6 +++++ 2 files changed, 72 insertions(+) create mode 100644 11_facade.cpp diff --git a/11_facade.cpp b/11_facade.cpp new file mode 100644 index 0000000..4da6954 --- /dev/null +++ b/11_facade.cpp @@ -0,0 +1,66 @@ +#include +#include + + +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 pro; + unique_ptr amp; +public: + Player(unique_ptr p, unique_ptr 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(); + auto amp = make_unique(); + 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(); + auto amp = make_unique(); + pro->set_brightness(20); + amp->set_volume(42); + amp->set_mode("Virtual Surround"); + Player p(move(pro), move(amp)); + p.play("CSAPP"); +} diff --git a/notes.md b/notes.md index 392a020..ba746fa 100644 --- a/notes.md +++ b/notes.md @@ -71,3 +71,9 @@ 有时,我们需要给动态的一个类添加一些组件。例如:对于制作一杯咖啡,可以添加牛奶,糖等。一种做法是使用继承,这显然会造成类爆炸。另一种做法是将这些配料抽象成一个类,咖啡类维护一个配料的列表。对于纯数据,如计算最终价格,这样是合理的。但是对于添加额外行为,这就会将逻辑集中到 Coffee 类中。例如希望添加牛奶时咖啡必须加热,就不得不修改 Coffee 类,在它的 make 函数中添加处理逻辑。 装饰器模式解决了这个问题。让所有的配料都继承自 Coffee,构建时则额外需要一个被装饰对象的指针,构造函数中还能插入额外的处理。这样可以让每一层都能主动拦截、加工、改写行为,而不需要集中到一个地方。对于客户端代码来说,装饰器和原对象是一样的。当需要对咖啡做某个动作时,可以对装饰器做,装饰器再调用被修饰对象指针的对应动作。由于包含关系,装饰器还天然记录了顺序。 + +## 外观模式(Facade) + +在一个复杂系统中,往往由多个子系统协同工作来完成一项功能。例如,一个编译器可能包含词法分析器、语法分析器、语义分析器、优化器和代码生成器等多个模块。如果每次都要让调用者直接与这些子系统交互,不仅复杂、容易出错,而且对用户也不友好。而实际上,许多操作是常用的、固定的组合,例如“编译整个程序”就总是涉及所有子模块的调用顺序。 + +很容易想到通过一个统一的入口,也就是新增一个“外观类”或“外观函数”,封装这些子系统的内部调用逻辑。这就是外观模式,对外提供一个简化接口,同时又保留了对细节的操控能力。