C++设计模式_结构型模式_外观模式Facade

本文记录外观模式。

外观模式(Facade)又称为门面模式,是最简单的模式。该模式的作用是用来隔离接口,就是扮演中间层的角色,把结合紧密的两部分分割开,让这两部分内容通过中间层来打交道,类似于依赖倒置原则,高层和底层依赖于抽象层。从而极大的降低了两部分的耦合性。

一个配置相关的范例

一个游戏有如下配置:图形配置,声音配置和语音聊天配置,创建这三个类,因为这些类在项目中只保持一个对象即可,因此将这三个类设计为单例类。

cpp 复制代码
    class Graphic
    {
    private:
        Graphic() {};
        ~Graphic() {};
        Graphic(const Graphic& ojb) {}
        Graphic& operator=(const Graphic& obj) {}

    public:
        static Graphic& getInstance()
        {
            static Graphic instance;
            return instance;
        }
    public:
        void displayFull(bool enable) // 显示全屏
        {
            cout << "displayFull" << endl;
        }
        void effect(bool enable) // 显示特效
        {
            cout << "effect" << enable << endl;
        }
        void resolution(int w, int h) //设置窗口分辨率
        {
            cout << "窗口分辨率宽:" << w << "分辨率高:" << h << endl;
        }
        void antialiasing(bool enable) // 抗锯齿
        {
            cout << "不开启抗锯齿 antialiasing" << endl;
        }
    };

    class Sound
    {
    public:
        Sound() {};
        ~Sound() {};
        Sound(const Sound& ojb) {}
        Sound& operator=(const Sound& obj) {}
    public:
        static Sound& getInstance()
        {
            static Sound instance;
            return instance;
        }
    public:
        void volume(int v) // 设置音量
        {
            cout << "设置音量大小:" << v << endl;;
        }

        void setenvironmentVolume(int ev)
        {
            cout << "开启环境音量 << " << ev << endl;
        }

        void setvolume(int v)
        {
            cout << "设置音量大小为:" << v << endl;
        }
    };

    class chatVoice
    {
    private:
        chatVoice() {};
        ~chatVoice() {};
        chatVoice(const chatVoice& ojb) {}
        chatVoice& operator=(const chatVoice& obj) {}
    public:
        static chatVoice& getInstance()
        {
            static chatVoice instance;
            return instance;
        }
    public:
        void setMicVoice(int v)
        {
            cout << "设置麦克风音量" << v << endl;
        }

        void setMicSense(int s)
        {
            cout << "设置麦克风灵敏度" << endl;
        }

        void setChatVolume(int c)
        {
            cout << "聊天音量为 " << c << endl;
        }
    };

    void test()
    {
        Graphic& g1 = Graphic::getInstance();
        g1.displayFull(true);
        g1.effect(true);
        g1.antialiasing(true);
        g1.resolution(1920, 1080);

        Sound& s1 = Sound::getInstance();
        s1.setenvironmentVolume(100);
        s1.setvolume(100);
        s1.volume(100);

        chatVoice& c1 = chatVoice::getInstance();
        c1.setChatVolume(100);
        c1.setMicSense(100);
        c1.setMicVoice(111);

        /*
        displayFull
    effect1
    不开启抗锯齿 antialiasing
窗口分辨率宽:1920分辨率高:1080
开启环境音量 << 100
设置音量大小为:100
设置音量大小:100
聊天音量为 100
设置麦克风灵敏度
设置麦克风音量111
        */
    }

通过结果可以看出,达到了设计这些类的目的。

引入外观(facade)模式

上面的代码中,在void test()类中(由main函数调用)的上面两个类Graphic ,Sound类的接口称为客户端代码,把这些具体的类称为业务类;上边代码中的test()中体现了客户端代码和业务类代码的直接交互,这不是一种好的设计方法。

现在希望将业务类和客户端代码解耦,实现一个新类,扮演中间层的角色,客户端代码不在需要直接与业务类打交道,而是直接和中间类打交道,这个中间的类就是外观模式类,该类对客户端提供了一些简单的调用接口,客户端直接通过这些简单的接口达到调用业务类的目的,新的设计如下图所示:

外观模式强调的是一种程序设计思想,并不是一种特殊的编程手法。上面代码加了一个新类Façade类,实现了客户端代码和业务代码的解耦,代码设计如下:

cpp 复制代码
    class Graphic
    {
    private:
        Graphic() {};
        ~Graphic() {};
        Graphic(const Graphic& ojb) {}
        Graphic& operator=(const Graphic& obj) {}

    public:
        static Graphic& getInstance()
        {
            static Graphic instance;
            return instance;
        }
    public:
        void displayFull(bool enable) // 显示全屏
        {
            cout << "displayFull" << endl;
        }
        void effect(bool enable) // 显示特效
        {
            cout << "effect" << enable << endl;
        }
        void resolution(int w, int h) //设置窗口分辨率
        {
            cout << "窗口分辨率宽:" << w << "分辨率高:" << h << endl;
        }
        void antialiasing(bool enable) // 抗锯齿
        {
            cout << "不开启抗锯齿 antialiasing" << endl;
        }
    };

    class Sound
    {
    public:
        Sound() {};
        ~Sound() {};
        Sound(const Sound& ojb) {}
        Sound& operator=(const Sound& obj) {}
    public:
        static Sound& getInstance()
        {
            static Sound instance;
            return instance;
        }
    public:
        void volume(int v) // 设置音量
        {
            cout << "设置音量大小:" << v << endl;;
        }

        void setenvironmentVolume(int ev)
        {
            cout << "开启环境音量 << " << ev << endl;
        }

        void setvolume(int v)
        {
            cout << "设置音量大小为:" << v << endl;
        }
    };

    class chatVoice
    {
    private:
        chatVoice() {};
        ~chatVoice() {};
        chatVoice(const chatVoice& ojb) {}
        chatVoice& operator=(const chatVoice& obj) {}
    public:
        static chatVoice& getInstance()
        {
            static chatVoice instance;
            return instance;
        }
    public:
        void setMicVoice(int v)
        {
            cout << "设置麦克风音量" << v << endl;
        }

        void setMicSense(int s)
        {
            cout << "设置麦克风灵敏度" << endl;
        }

        void setChatVolume(int c)
        {
            cout << "聊天音量为 " << c << endl;
        }
    };
    class Facade
    {
    private:
        Facade() {};
        ~Facade()
        {

        }
        Facade(const Facade& ojb) {}
        Facade& operator=(const Facade& obj) {}

    public:
        static Facade& getInstance()
        {
            static Facade instance;
            return instance;
        }
    public:
        // 定义一个高配置的方法
        void getHighConfig()
        {
            Graphic& g1 = Graphic::getInstance();
            g1.displayFull(true);
            g1.effect(true);
            g1.antialiasing(true);
            g1.resolution(1920, 1080);

            Sound& s1 = Sound::getInstance();
            s1.setenvironmentVolume(100);
            s1.setvolume(100);
            s1.volume(100);

            chatVoice& c1 = chatVoice::getInstance();
            c1.setChatVolume(100);
            c1.setMicSense(100);
            c1.setMicVoice(111);
        }

        void getLowConfig()
        {
            Graphic& g1 = Graphic::getInstance();
            g1.displayFull(false);
            g1.effect(false);
            g1.antialiasing(false);
            g1.resolution(1024, 180);

            Sound& s1 = Sound::getInstance();
            s1.setenvironmentVolume(10);
            s1.setvolume(10);
            s1.volume(10);

            chatVoice& c1 = chatVoice::getInstance();
            c1.setChatVolume(10);
            c1.setMicSense(10);
            c1.setMicVoice(11);

        }
    };
    // 定义一个低配置的方法   
    void test2()
    {
        Facade& f1 = Facade::getInstance();
        f1.getHighConfig();
        f1.getLowConfig();

    }

迪米特法则--- 原则5

外观模式体现了面向对象程序设计的一个原则---迪米特原则,该原则如下:一个对象对其他对象的了解应该尽可能少,从而降低了对象之间的耦合,提高系统的可维护性。例如,在一个系统中,模块之间调用时,通过提供一个统一的接口来实现,这样其他模块就不需要了解另外一个模块内部的实现细节了,当一个模块内部发生改变时,也不会影响到其他模块。

外观模式有两种角色:

外观角色Façade ,客户端用Façade角色的方法,该方法将客户端的请求传递到业务类中。

子系统角色:子系统就是业务类 Graphic Sound chatVoice 类,这些子类被外观类调用。

外观模式定义:提供了一个统一的接口,用来访问子系统中的一群接口。

另一个外观模式的范例

下面的例子也是一个外观模式的例子,在这个例子中,Façade 是外观角色,其调用了其他的类的接口,实现了和客户端的解耦。

cpp 复制代码
// Screen Light  Speaker DvdPlayer PlayerStation
 class Screen
 {
 public:
     void On()
     {
         cout << "打开屏幕" << endl;
     }
     void Off()
     {
         cout << "关闭屏幕" << endl;
     }
 };
 class Light
 {
 public:
     void On()
     {
         cout << "打开屏幕" << endl;
     }
     void Off()
     {
         cout << "关闭屏幕" << endl;
     }
 };

 class Speaker
 {
 public:
     void On()
     {
         cout << "打开屏幕" << endl;
     }
     void Off()
     {
         cout << "关闭屏幕" << endl;
     }
 };

 class Facade
 {
 public:

     void On()
     {
m_screen.On();
m_light.On();
m_speaker.On();
		}
     void Off()
     {
m_screen.Off();
m_light.Off();
m_speaker.Off();
		}

 private:
     Screen m_screen;
     Light m_light;
     Speaker m_speaker;
 };

 void test()
 {
		Facade f1;
		f1.On();
		f1.Off();
	}

UML图如下:

相关推荐
李广坤4 小时前
策略模式(Strategy Pattern)
设计模式
FreeBuf_4 小时前
Happy DOM曝CVSS 9.4严重RCE漏洞,PoC已公开(CVE-2025-61927)
java·c语言·c++·python·php
BlackQid4 小时前
深入理解指针Part4——字符、数组与函数指针变量
c++·后端
Vect__4 小时前
从底层到上层的“外挂”:deque、stack、queue、priority_queue 全面拆解
数据结构·c++
草莓熊Lotso4 小时前
C++ 手写 List 容器实战:从双向链表原理到完整功能落地,附源码与测试验证
开发语言·c++·链表·list
wxin_VXbishe4 小时前
基于SpringBoot的天天商城管理系统的设计与现-计算机毕业设计源码79506
java·c++·spring boot·python·spring·django·php
初圣魔门首席弟子4 小时前
const string getWord() ;和 string getWord() const ;是一样的效果吗
开发语言·c++
泽虞5 小时前
《Qt应用开发》笔记p3
linux·开发语言·数据库·c++·笔记·qt·面试
ajassi20005 小时前
开源 C++ QT QML 开发(十八)多媒体--音频播放
c++·qt·开源