設計模式以外觀模式

2018-09-20 01:33:12linux

外觀模式(Facade Pattern)

  仍是用大話設計模式中的例子:股票和基金來講明外觀模式。股票買入者直接操做股票,他須要瞭解幾千只股票的各類信息還須要預測它的漲跌,這樣買入者和股票直接有着直接的聯繫,在軟件開發種,這就是高耦合(模塊和模塊之間的聯繫過多)。買入基金,則由專業的基金經理人操做用戶的資源,買入者只須要和基金經理人打交道,具體股票的細節,則由基金經理人來處理。ios

  外觀模式(Facade Pattern)又稱門面模式:爲子系統中的一組接口提供一個一致的界面,此模式定義了一個高層接口,這個接口使得這一子系統更加容易使用。設計模式

UML類圖

其中:SubSystemOne、SubSystemTwo、SubSystemThree、SubSystemFour 構成了一個子系統。bash

Facade:外觀類,知道哪些子系統,它們有哪些功能,通常Client把像子系統的請求委託給Facade,而後Facade再把這個請求轉給適合的子系統對象。(System和Facade實際上是聚合關係,它們之間沒有太多的耦合性)架構

SubSystem:子系統,子系統能夠同時有多個,一個系統能夠是類的集合或者是一個單獨的類。每一個子系統能夠單獨被Client調用也能夠被Facade調用,對於Client來講它不知道有Facade的存在,Facade對子系統而言就是一個Client。ide

外觀模式的優缺點

優勢:函數

  1.Client只與Facade打交道,下降了Client代碼的複雜度。spa

  2.下降了Client和System的耦合度,子系統有調整時不會影響到Client或者影響較小,可以經過調整Facade來適應子系統的改變。設計

  3.下降了大型軟件中的編譯依賴性,並簡化了系統在不一樣平臺之間而定移植過程,由於設計良好的子系統,通常而言是相互獨立的,一個系統的改變不會影響到其它子系統,而子系統的內部變化(指實現細節)也不會影響到外觀,因此只須要編譯有變化的子系統便可(對GCC編譯器)。code

  4.模式僅提供了一個訪問子系統的統一入口,可是並不阻止用戶直接使用子系統類。

 

缺點:

  1.不能很好地限制Client使用子系統,若是要給Client添加使用限制,將多是整個模式喪失它的靈活性,也會增長其複雜度(試想一下爲每一個子系統添加定製化的限制,在實現是將會有多複雜)

  2.在不引入抽象外觀類(Facade)的狀況下,增長子系統,要對應的調整Facade和Client(考慮下簡單工廠模式),這會違背開放-封閉原則。

使用場景

  • 當要爲一個複雜子系統提供一個簡單接口時。該接口能夠知足大多數用戶的需求,並且用戶也能夠越過外觀類直接訪問子系統。
  • Client 與多個子系統之間存在很大的依賴性。引入外觀類將子系統與 Client 以及其餘子系統解耦,能夠提升子系統的獨立性和可移植性。
  • 在層次化結構中,可使用外觀模式定義系統中每一層的入口。層與層之間不直接產生聯繫,而經過外觀類創建聯繫,下降層之間的耦合度。

代碼示例

  問題模型:假設咱們在開發一個GUI程序,經過界面咱們可以產生一組通用數據,可是這組通用數據須要被不一樣的子系統按需選擇,並進行對應的處理。好比咱們能在bash終端輸入不一樣的命令調用不一樣的處理程序。咱們假設這是一個外觀模式(但真實的應用狀況不是這樣,由於,linux下的各類命令其實是由我的開發者自行開發的程序,在使用時,bash終端輸入程序名 參數便可使用命令提供的服務)。那麼如今main函數就是客戶代碼,S1表示調用子系統S1執行某種操做,S2表示調用S2執行某種操做等等。網上有個電商的例子,我以爲比較好,它沒有我這個這麼理想化,子系統之間的數據沒有耦合。

1.3個子系統

#ifndef SUBSYSTEMA_H_
#define SUBSYSTEMA_H_

#include <iostream>

class SubSystemA
{
public:
    void methodA()
    {
    std::cout << "I am SystemA!" << std::endl;
    }
    SubSystemA() = default;
    ~SubSystemA() = default;
};
#endif
SubSystemA
#ifndef SUBSYSTEMB_H_
#define SUBSYSTEMB_H_
#include <iostream>
#include <ctime>
class SubSystemB
{
public:
    void methodB()
    {
    auto systTime = time(nullptr);
        tm *struSysTime = localtime(&systTime);
    char szTime[16] = {0};
        sprintf(szTime,"%04d-%02d-%02d",struSysTime->tm_year+1990,struSysTime->tm_mon+1,struSysTime->tm_mday);
    std::cout << "Today is:" << szTime << std::endl;
    }
    SubSystemB() = default;
    ~SubSystemB() = default;
};
#endif
SubSystemB
#ifndef SUBSYSTEMC_H_
#define SUBSYSTEMC_H_

#include <iostream>
#include <ctime>

class SubSystemC
{
public:
    void methodC()
    {
    auto systTime = time(nullptr);
    tm *struSysTime = localtime(&systTime);
        char szTime[16] = {0};
        sprintf(szTime,"%02d:%02d:%02d",struSysTime->tm_hour,struSysTime->tm_min,struSysTime->tm_sec);
    std::cout << "Now Time is:"<< szTime << std::endl;
    }
    SubSystemC() = default;
    ~SubSystemC() = default;
};
#endif
SubsystemC

2.Facade外觀類,也是這個模式的核心

#ifndef FACADE_H_
#define FACADE_H_
#include "SubSystemA.h"
#include "SubSystemB.h"
#include "SubSystemC.h"
#include <string>
class Facade
{
public:
    void noteSubSystem(const std::string strParam);
    Facade() = default;
    ~Facade() = default;
private:
    SubSystemA m_objSubSystemA;
    SubSystemB m_objSubSystemB;
    SubSystemC m_objSubSystemC;
};
#endif 

#include "Facade.h"

void Facade::noteSubSystem(const std::string strSystemName)
{
    if(strSystemName == "SubSystemA")
    m_objSubSystemA.methodA();
    else if(strSystemName == "SubSystemB")
    m_objSubSystemB.methodB();
    else if(strSystemName == "SubSystemC")
    m_objSubSystemC.methodC();
    else
    std::cout << "Param Error" << std::endl;
}    
Facade

3.客戶端代碼

#include "Facade.h"

using namespace std;

int main(int argc,char*argv[])
{
    if(argc != 2)
    {
    std::cout << "The count of param is Error!" <<std::endl;
    return (0);
    }
    std::string strParam = argv[1];
    Facade objFacade;
    objFacade.noteSubSystem(strParam);
    return (1);
}
Client

 

  外觀模式的使用:

  1.在設計階段就要有意識的把不一樣的層分離(三層架構:數據訪問層、業務邏輯層、表示層,在層與層之間創建外觀Facade)

  2.開發階段,子系統由於不斷的重構變的愈來愈複雜。增長外觀模式。能夠提供一個簡單的接口,減小它們之間的依賴

  3.爲新系統開發一個外觀Facade類,來提供設計粗糙或高度負責的遺留代碼的比較清晰簡單的接口,讓新系統與Facade對象交互,Facade與遺留代碼交互全部的複雜工做。

 

 

 

 

 

 

 

d

相關文章
相關標籤/搜索