设计模式之外观模式

外观模式(Facade Pattern)

定义

定义了一个高层接口,该接口为子系统中的一组接口提供一个一致的界面,使得这一子系统更加容易使用。

 

常用场景

  • 当你要为一个复杂子系统提供一个简单接口时。子系统往往因为不断演化而变的越来越复杂。大多数模式使用时都会产生更多更小的类。这使得子系统更具有可重用性,也更容易对子系统进行定制,但这也给那些不需要定制子系统的用户带来一些使用上的困难。外观模式可以提供一个简单的缺省视图,这一视图对大多数用户来说已经足够,而那些需要更多的可定制性的用户可以越过Facade层;
  • 当客户程序与抽象类的实现部分之间存在很大的依赖性。引入Facade将这个子系统与客户以及其他的子系统分离,可以提高子系统的独立性和可移植性;
  • 当需要构建一个层次结构的子系统时,使用外观模式定义子系统中每层的入口点。如果子系统之间是相互依赖的,我们就可以让它们仅通过Facade进行通讯,从而简化了它们之间的依赖关系。

 

优点

  •  松散耦合
    • 外观模式松散了客户端与子系统的耦合关系,让子系统内部的模块能更容易扩展和维护。即要点2.
  •  简单易用
    • 外观模式让子系统更加易用,客户端不再需要了解子系统内部的实现,也不需要跟众多子系统内部的模块进行交互,只需要跟外观交互就可以了,相当于外观类为外部客户端使用子系统提供了一站式服务。
  •  更好的划分访问层次
    • 通过合理使用Facade,可以帮助我们更好的划分访问的层次。有些方法是对系统外的,有些方法是系统内部使用的。把需要暴露给外部的功能集中到外观中,这样既方便客户端使用,也很好的隐藏了内部的细节。

 

缺点

过多的或者是不太合理的Facade也容易让人迷惑,到底是调用Facade好呢,还是直接调用模块好

 

C++实现

举例:手机

手机本身对我们来说就是一个外观系统。手机内部有开关机、照相、下载、删除、打接电话、收发信息等功能,每个功能都是一个子系统。对于我们来说,不需要清楚地知道每个子系统的运行原理,只需要点击屏幕上的相关按钮即可完成操作,系统内部会完成相关的调用。

类图:

                  设计模式之外观模式

 

  • Facade:知道哪些子系统类负责处理请求,并且将客户的请求代理给适当的子系统对象;
  • SubSystem:实现子系统具体的功能;处理由Facade对象指派的任务;但是,SubSystem没有Facade的任何相关信息,也就是说,没有指向Facade的指针。
  • Client:通过发送请求给Facade的方式与子系统进行通信,而不直接与子系统打交道,Facade将这些消息转发给适当的子系统对象。尽管是子系统中的有关对象在做实际工作,但Facade模式本身也必须将它的接口转换成子系统的接口,这里是不是有点适配器模式的感觉呢?这就是学习结构型设计模式的感觉,感觉都很相似,但是仔细的去研究时,就会发现各自的用处。

代码:

#include <iostream>
#include <string>

using std::cout;
using std::endl;

// 开关机系统
class OnOffSystem
{
public:
    void On()
    {
        std::cout << "手机开机." << std::endl;
    }

    void Off()
    {
        std::cout << "手机关机." << std::endl;
    }
};

// 照相系统
class PhotoSystem
{
public:
    void Photo()
    {
        std::cout << "拍照." << std::endl;
    }

    void Viedo()
    {
        std::cout << "录制视频." << std::endl;
    }
};

// 打接电话系统
class CallSystem
{
public:
    void Call()
    {
        std::cout << "打电话." << std::endl;
    }

    void Pick()
    {
        std::cout << "接电话." << std::endl;
    }
};

class Phone  
{
public:
    Phone() : m_onOffSystem(nullptr), m_photoSystem(nullptr), m_callSystem(nullptr)
    {

    }

    void SetOnOff(OnOffSystem* system) 
    {
        m_onOffSystem = system;
    }

    void SetPhoto(PhotoSystem* system) 
    {
        m_photoSystem = system;
    }

    void SetCall(CallSystem* system) 
    {
        m_callSystem = system;
    }

    void On()
    {
        if (m_onOffSystem)
            m_onOffSystem->On();
    }

    void Off()
    {
        if (m_onOffSystem)
            m_onOffSystem->Off();
    }

    void Photo()
    {
        if (m_photoSystem)
            m_photoSystem->Photo();
    }

    void Vedio()
    {
        if (m_photoSystem)
            m_photoSystem->Viedo();
    }

    void Call()
    {
        if (m_callSystem)
            m_callSystem->Call();
    }

    void Pick()
    {
        if (m_callSystem)
            m_callSystem->Pick();
    }

private:
    OnOffSystem* m_onOffSystem;   // 外部引用,不需释放
    PhotoSystem* m_photoSystem;   // 按需装载, 可以没有,功能也没有
    CallSystem* m_callSystem;
};

int FacadeTest(int argc, char** argv)
{
    Phone* pFacade = new Phone;
    OnOffSystem* pOnOffSystem = new OnOffSystem;
    PhotoSystem* pPhotoSystem = new PhotoSystem;
    CallSystem* pCallSystem = new CallSystem;

    pFacade->SetOnOff(pOnOffSystem);
    //pFacade->SetPhoto(pPhotoSystem);  // 不装载此功能
    pFacade->SetCall(pCallSystem);

    pFacade->On();
    pFacade->Photo();
    pFacade->Photo();
    pFacade->Vedio();
    pFacade->Call();
    pFacade->Call();
    pFacade->Pick();
    pFacade->Off();

    delete pCallSystem;
    delete pPhotoSystem;
    delete pOnOffSystem;
    delete pFacade;

    return 0;
}

设计模式之外观模式