大家有做项目的时候,有没有这样的经历,
①我们项目本来很精简,但是随着项目的不断完善,扩充,功能越来越复杂,类体系也越来越复杂。很多时候工作,一个很简单的事情,我们需要调研那个很多到工序才能完成。这样维护起来代码,无论是谁都会感到很累。但其实这时候那些内部逻辑我们都没必要了解了,一个简单的接口反而更加适合我们的操作, 更加这时候外观模式就派上用途了。
②或者说我们在开发的时候要用到一个第三方库,这些库操作很底层,我们每次要调用,都需要调用很多类,例如我们在用ffmpeg和sdl库进行嵌入式视频库的开发的时候,每次都要加锁,,读取包,解码,等等,我们就可以用外观模式将这些接口封装起来,这样我们每次调用,只需要调用我们封装好的接口。
对比现实中的例子,
①比如说,我们喝茶,如果是自己泡茶需要自行准备茶叶、茶具和开水,但是我们其实部需要了解这些,我们只需要一个结果,就是那个泡好的茶,于是我们去了茶馆,我们只需要跟茶馆服务员说想要一杯什么样的茶,是铁观音、碧螺春还是西湖龙井?正因为茶馆有服务员,顾客无须直接和茶叶、茶具、开水等交互,整个泡茶过程由服务员来完成,顾客只需与服务员交互即可,整个过程非常简单省事,这时候,茶馆或者说服务员就像一个外观模式,将所有我们不关心的,或者无需了解的操作封装(隐藏)起来,只给了我们一个结果。
②再例如说我们去邮局寄信,我们并不关心信是怎么寄的,我们(客户端)只需要调用一个叫做邮寄的方法,邮局的邮递员就自行把邮件给我们邮寄出去了,这时候就相当于,邮递员这个外观,将邮寄信的方法都给我们封装隐藏起来,我们使用起来也方便不少。
③比如说我们使用编译器,编译我们的代码,其实我们需要,经过预处理,词法,语法,语义,中间代码生成,汇编,链接,但是我们不需要了解这个,We don’t want to konw it,,因此出现了IDE,例如Visual,CodeBlocks,DevCpp,Eclipce等,我们只需要一个Build,好了一切都完成了。
说了这么多这就是外观模式,它有几个好处(摘自DP一书),
(1)它对客户屏蔽子系统组件,因而减少了客户处理的对象的数目并使得子系统使用起来更加方便。
(2)它实现了子系统与客户之间的松耦合关系,而子系统内部的功能组件往往是紧耦合的。
(3)如果应用需要,它并不限制它们使用子系统类。
#include <iostream> using namespace std; // 词法分析 class Lexicaler { public : void Lexical( ) { std::cout <<"正在对源文件进行词法分析" <<std::endl; } }; // 语法分析 class Parser { public : void Parse( ) { std::cout <<"正在对源文件进行语法分析" <<std::endl; } }; // 语义分析 class Semantier { public : void Semantic( ) { std::cout <<"正在对源文件进行语义分析" <<std::endl; } }; // 生成中间代码 class Gener { public : void Gen( ) { std::cout <<"正在生成目标代码" <<std::endl; } }; // 生成中间代码 class Asmer { public : void Asm( ) { std::cout <<"正在生成目标代码" <<std::endl; } }; // 连接 class Linker { public : void Link( ) { std::cout <<"正在生成链接" <<std::endl; } }; class Complier { public : void Comple( ) { Lexicaler lexicaler; Parser parser; Semantier semantier; Gener gener; Asmer asmer; Linker linker; lexicaler.Lexical( ); parser.Parse( ); semantier.Semantic( ); gener.Gen( ); asmer.Asm( ); linker.Link( ); } }; int main(void) { // 这是不用外观模式的代码 // 但是其实我们并不关心编译的过程, // 我们需要的只是编译的结果, // 那个可执行程序才是我们想要的 Lexicaler lexicaler; Parser parser; Semantier semantier; Gener gener; Asmer asmer; Linker linker; lexicaler.Lexical( ); parser.Parse( ); semantier.Semantic( ); gener.Gen( ); asmer.Asm( ); linker.Link( ); // 使用外观模式 Complier complier; complier.Comple( ); }