大家有做项目的时候,有没有这样的经历,
①我们项目本来很精简,但是随着项目的不断完善,扩充,功能越来越复杂,类体系也越来越复杂。很多时候工作,一个很简单的事情,我们需要调研那个很多到工序才能完成。这样维护起来代码,无论是谁都会感到很累。但其实这时候那些内部逻辑我们都没必要了解了,一个简单的接口反而更加适合我们的操作, 更加这时候外观模式就派上用途了。
②或者说我们在开发的时候要用到一个第三方库,这些库操作很底层,我们每次要调用,都需要调用很多类,例如我们在用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( );
}
好了外观模式,就是将那些 Client don’t want to konw 的事情封装起来,对客户端隐蔽。