外观模式,是一种把子系统和客户端做松耦合操作的一个设计模式。这样客户端调用系统,根本不需要知道系统内部是如何操作的,只需要调用外部“接待员”即可,所以即使子系统有变化时,也不需要客户端做改变,达到松耦合的效果。
我们通过外观的包装,使应用程序只能看到外观对象,而不会看到具体的细节对象,这样无疑会降低应用程序的复杂度,并且提高了程序的可维护性。
外观模式包含三个角色:
外观角色(Facade):是模式的核心,他被客户client角色调用,知道各个子系统的功能。同时根据客户角色已有的需求预订了几种功能组合
子系统角色(Subsystem classes):实现子系统的功能,并处理由Facade对象指派的任务。对子系统而言,facade和client角色是未知的,没有Facade的任何相关信息;即没有指向Facade的实例。
客户角色(client):调用facade角色获得完成相应的功能。
主要解决:降低访问复杂系统的内部子系统时的复杂度,客户端与子系统松耦合。
何时使用: 1、客户端不需要知道系统内部的复杂联系,整个系统只需提供一个"接待员"即可。 2、定义系统的入口。
如何解决:客户端不与系统耦合,外观类与系统耦合。
关键代码:在客户端和复杂系统之间再加一层,这一次将调用顺序、依赖关系等处理好。
应用实例: 1、去医院看病,可能要去挂号、门诊、划价、取药,让患者或患者家属觉得很复杂,如果有提供接待人员,只让接待人员来处理,就很方便。
优点: 1、减少系统相互依赖。 2、提高灵活性。 3、提高了安全性。
缺点:不符合开闭原则,如果要改东西很麻烦,继承重写都不合适。
使用场景: 1、为复杂的模块或子系统提供外界访问的模块。 2、子系统相对独立。 3、预防低水平人员带来的风险。
注意事项:在层次化结构中,可以使用外观模式定义系统中每一层的入口。
下边时一个开车和停车操作的例子,两个操作,在不调用和调用外观模式的时候的代码:
<?php
//子系统角色
//车门
class CarDoor{
public function Open()
{
echo "Open the door. ";
}
public function Close()
{
echo "Close the door. ";
}
}
//发动机
class Engine{
public function Start()
{
echo "Start Engine. ";
}
public function Stop()
{
echo "Stop Engine. ";
}
}
//踩油门
class Accelerator{
public function Run()
{
echo "Press the accelerator. ";
}
}
//踩刹车
class Breaking {
public function Run()
{
echo "Break. ";
}
}
//如果不采用外观模式,那么开车和停车的调用如下
$CarDoor = new CarDoor();
$Engine = new Engine();
$Accelerator = new Accelerator();
$Breaking = new Breaking();
//开车
$CarDoor->Open();
$Engine->Start();
$Accelerator->Run();
//停车
$Breaking->Run();
$Engine->Stop();
$CarDoor->Close();
//采用外观模式.定义外观角色
class Facade{
private $CarDoor;
private $Engine;
private $Accelerator;
private $Breaking;
function __construct()
{
$this->CarDoor = new CarDoor();
$this->Engine = new Engine();
$this->Accelerator = new Accelerator();
$this->Breaking = new Breaking();
}
public function Start()
{
$this->CarDoor->Open();
$this->Engine->Start();
$this->Accelerator->Run();
}
public function Stop()
{
$this->Breaking->Run();
$this->Engine->Stop();
$this->CarDoor->Close();
}
}
//调用外观模式
$Facade = new Facade();
//开车
$Facade->Start();
//停车
$Facade->Stop();
?>