一、简介
外观模式(Facade Pattern)隐藏系统的复杂性,并向客户端提供了一个客户端可以访问系统的接口。这种类型的设计模式属于结构型模式,它向现有的系统添加一个接口,来隐藏系统的复杂性。
这种模式涉及到一个单一的类,该类提供了客户端请求的简化方法和对现有系统类方法的委托调用。
我们可以将这个类看作是复杂系统的外观,对客户端提供调用系统实现某种功能的接口,而如何调用(对系统接口的调用顺序和调用依赖)不对客户端展示,由外观类自己处理。
二、外观模式实例
我们知道新生入学是十分麻烦的事情,需要办理各种手续,甚至可以让学生和家长忙碌一整天。假如某院校提供一批接待人员帮助新生办理新生入学事务,而新生只需要提供本人身份信息给接待人员即可。
在这个事例中,新生入学系统就是一个复杂的系统;新生是客户端;接待人员可以看做入学系统的外观。
下面用代码来体现
1)复杂系统-入学系统的基类
class AdmissionSystem
{
public:
AdmissionSystem() {}
virtual ~AdmissionSystem() {}
void GetStudentID()
{
cout << "领取学生证" << endl;
}
void ConfirmDormitory()
{
cout << "确认宿舍+床位号" << endl;
}
void GetTextBook()
{
cout << "领取教材" << endl;
}
virtual void ConfirmClass() = 0;
};
2)复杂系统的子系统-各个学院的入学系统
子系统可能存在不同的执行步骤、不同的功能和不同的依赖
//理学院入学系统
class FacultyOfScience : public AdmissionSystem
{
public:
void ConfirmClass()
{
cout << "进入理学院:确认学生班级" << endl;
}
};
//工学院入学系统
class FacultyOfEngineering : public AdmissionSystem
{
public:
void ConfirmClass()
{
cout << "进入工学院:确认学生班级" << endl;
}
void GetComputer()
{
cout << "领取电脑" << endl;
}
};
//艺术学院入学系统
class FacultyOfArt : public AdmissionSystem
{
public:
void ConfirmClass()
{
cout << "进入艺术学院:确认学生班级" << endl;
}
void ConfirmActivityRoom()
{
cout << "确认学生活动室" << endl;
}
};
3)外观模式的重点-外观类:入学系统的接待人员
//接待人员
class AdmissionSystemHandlers
{
public:
AdmissionSystemHandlers()
{
_scienceHandler = new FacultyOfScience();
_engineerHandler = new FacultyOfEngineering();
_artHandler = new FacultyOfArt();
}
~AdmissionSystemHandlers()
{
delete _scienceHandler;
delete _engineerHandler;
delete _artHandler;
_scienceHandler = nullptr;
_engineerHandler = nullptr;
_artHandler = nullptr;
}
//入学理学院
void ScienceAdmission()
{
if (nullptr == _scienceHandler)
{
cout << "不存在接待人员" << endl;
return;
}
_scienceHandler->GetStudentID();
_scienceHandler->ConfirmClass();
_scienceHandler->ConfirmDormitory();
_scienceHandler->GetTextBook();
}
//入学工学院
void EngineerAdmission()
{
if (nullptr == _engineerHandler)
{
cout << "不存在接待人员" << endl;
return;
}
_engineerHandler->GetStudentID();
_engineerHandler->ConfirmClass();
_engineerHandler->ConfirmDormitory();
_engineerHandler->GetTextBook();
_engineerHandler->GetComputer();
}
//入学艺术学院
void ArtAdmission()
{
if (nullptr == _artHandler)
{
cout << "不存在接待人员" << endl;
return;
}
_artHandler->GetStudentID();
_artHandler->ConfirmClass();
_artHandler->ConfirmDormitory();
_artHandler->GetTextBook();
_artHandler->ConfirmActivityRoom();
}
private:
FacultyOfScience* _scienceHandler;
FacultyOfEngineering* _engineerHandler;
FacultyOfArt* _artHandler;
};
4)使用
int main(int argc, char *argv[])
{
AdmissionSystemHandlers hander;
//学生甲:入学理学院
cout << "学生甲申请入学理学院" << endl;
hander.ScienceAdmission();
cout << endl;
//学生乙:入学艺术学院
cout << "学生乙申请入学艺术学院" << endl;
hander.ArtAdmission();
system("pause");
return 0;
}
5)输出
三、总结
从上述实例可以看见,对于客户端(学生)来说,只要知道想要实现的功能(入学某某学院),就可以从外观类(入学系统接待人员)处一键获取结果。而客户端不需要知道如何使用这个复杂系统是才能实现这个功能,因为这部分工作都由外观类来完成。
这样,我们降低了客户端和系统的耦合性,不容易出错,对客户端使用系统更加友好。
但是它也存在缺点,即外观模式不符合开闭原则。如何需要新增对客户端提供的功能,需要修改外观类,而如果需要新增实现某个功能的步骤和逻辑,也要对现有接口进行修改。