設計模式C++之六(Facade門面模式)

 

Facade門面模式,也是比較常用的一種模式,基本上所有軟件系統中都會用到 GOF 在《設計模式》一書中給出如下定義:爲子系統中的一組接口提供一個一致的界面, Facade 模式定義了一個高層接口,這個接口使得這一子系統更加容易使用。簡單說,就是將複雜的邏輯封裝起來,對外公開簡單的接口,由客戶程序調用。這裏舉了一個發送郵件的例子,我們理解爲電子郵件吧,普通的郵件應該不需要告訴郵局,我們寫的信件內容(呵呵有點較真了)。這個例子更詳細的內容及說明可以參考原作者博客:cbf4life.cnblogs.com。

9.1.解釋

main(),客戶

ILetterProcess,接口

CLetterProcessImpl,信件處理的4個函數

CLetterPolice,警察

CModenPostOffice,郵局

說明:郵局對外只有一個窗口,接收信件內容和郵件地址。對內調用郵件處理的4個函數。將複雜邏輯封裝在郵局的裏面,當需要增加警察來檢查信件時,只需在郵局內增加警察檢查信件的方法。

注意:將複雜邏輯封裝起來,對外只有一個簡單的接口。

看代碼:

//ILetterProcess.h

#pragma once
#include <iostream>
using std::string;
class ILetterProcess
{
public:
    ILetterProcess(void);
    virtual ~ILetterProcess(void);
    virtual void WriteContext(string context) = 0;
    virtual void FillEnvelope(string address) = 0;
    virtual void LetterIntoEnvelope() = 0;
    virtual void SendLetter() = 0;
};

//ILetterProcess.cpp

#include "StdAfx.h"
#include "ILetterProcess.h"
ILetterProcess::ILetterProcess(void)
{
}
ILetterProcess::~ILetterProcess(void)
{
}

//LetterprocessImpl.h

#pragma once
#include "iletterprocess.h"
class CLetterProcessImpl :
    public ILetterProcess
{
public:
    CLetterProcessImpl(void);
    ~CLetterProcessImpl(void);

    void WriteContext(string context);
    void FillEnvelope(string address);
    void LetterIntoEnvelope();
    void SendLetter();
};

//LetterProcessImpl.cpp

#include "StdAfx.h"
#include "LetterProcessImpl.h"
#include <iostream>
using std::string;
using std::cout;
using std::endl;
CLetterProcessImpl::CLetterProcessImpl(void)
{
}
CLetterProcessImpl::~CLetterProcessImpl(void)
{
}
void CLetterProcessImpl::WriteContext(string context)
{
    cout << "填寫信的內容... ..." << endl;
}
void CLetterProcessImpl::FillEnvelope(string address)
{
    cout << "填寫收件人地址及姓名... ..." << endl;
}
void CLetterProcessImpl::LetterIntoEnvelope()
{
    cout << "把信放到信封中..." << endl;
}
void CLetterProcessImpl::SendLetter()
{
    cout << "郵遞信件..." << endl;
}

//ModenPostOffice.h

#pragma once
#include "ILetterProcess.h"
#include "LetterProcessImpl.h"
#include "LetterPolice.h"
#include <iostream>
using std::string;
class CModenPostOffice
{
public:
    CModenPostOffice(void);
    ~CModenPostOffice(void);
    void SendLetter(string context, string address);
private:
    ILetterProcess *m_pLetterProcess;
    CLetterPolice *m_pLetterPolice;
};

//ModenPostOffice.cpp

#include "StdAfx.h"
#include "ModenPostOffice.h"
CModenPostOffice::CModenPostOffice(void)
{
    this->m_pLetterProcess = new CLetterProcessImpl();
    this->m_pLetterPolice = new CLetterPolice();
}
CModenPostOffice::~CModenPostOffice(void)
{
    delete m_pLetterProcess;
    delete m_pLetterPolice;
}
void CModenPostOffice::SendLetter( string context, string address )
{
    //幫忙寫信
    m_pLetterProcess->WriteContext(context);
    //寫好信封
    m_pLetterProcess->FillEnvelope(address);
    //警察要檢查信件了
    m_pLetterPolice->CheckLetter(m_pLetterProcess);
    //把信放到信封中
    m_pLetterProcess->LetterIntoEnvelope();
    //郵遞信件
    m_pLetterProcess->SendLetter();
}

//LetterPolice.h

#pragma once
#include "ILetterProcess.h"
class CLetterPolice
{
public:
    CLetterPolice(void);
    ~CLetterPolice(void);
    void CheckLetter(ILetterProcess *pLetterProcess);
};

//LetterPolice.cpp

#include "StdAfx.h"
#include "LetterPolice.h"
CLetterPolice::CLetterPolice(void)
{
}
CLetterPolice::~CLetterPolice(void)
{
}
void CLetterPolice::CheckLetter( ILetterProcess *pLetterProcess )
{

    //檢查信件,此處省略一萬字。
    return;
}

//Facade.cpp

#include "stdafx.h"
#include "ILetterProcess.h"
#include "LetterProcessImpl.h"
#include "ModenPostOffice.h"
#include<iostream>
using std::string;
using std::cout;
using std::endl;
void DoItByPostOffice()
{
    CModenPostOffice modenPostOffice;
    string context = "Hello, It's me, do you know who I am? I'm your old lover. I'd like to ... ...";
    string address = "Happy Road No. 666, Beijing City, China";
    modenPostOffice.SendLetter(context, address);
}
void DoItYourself()
{
    ILetterProcess *pLetterProcess = new CLetterProcessImpl();
    pLetterProcess->WriteContext("Hello, It's me, do you know who I am? I'm your old lover. I'd like to ... ...");
    pLetterProcess->FillEnvelope("Happy Road No. 666, Beijing City, China");
    pLetterProcess->LetterIntoEnvelope();
    pLetterProcess->SendLetter();
    delete pLetterProcess;
}
int _tmain(int argc, _TCHAR* argv[])
{
    //現在的調用方式。對於客戶來說確實簡單多了。
    //如需要增加邏輯,例如讓警察來檢查郵件。可以在郵局裏完成這項工作。
    DoItByPostOffice();
   
    //原來的調用方式。
    DoItYourself();

    _CrtSetDbgFlag(_CRTDBG_LEAK_CHECK_DF | _CRTDBG_ALLOC_MEM_DF);
    _CrtDumpMemoryLeaks();

    return 0;
}

上面的圖仍然只是類圖而已,用於幫助理解代碼中類之間的關係,而不是模式的抽象類圖。CModenPostOffice封裝了複雜的處理邏輯,對外只有SendLetter這個函數接口。使客戶程序容易瞭解到想要做什麼,應該告訴郵局什麼內容,郵局才能正確的工作。

目前爲止,還都是比較簡單的模式,越到後面越複雜。我的理解是當沒有模式的時候,大家編寫代碼也需要考慮擴展性、伸縮性、穩定性等等。那個時候大家寫程序都是自己在摸索經驗,逐漸的才意識到程序應該可以適應需求的變化。於是總結很多方法來,讓程序既能適應變化,又有一定的可靠性。這使得編程序更有趣,也更抽象了。所以軟件開發就是提煉和抽象的過程。類似於哲學的提煉,從特殊到一般。

發佈了8 篇原創文章 · 獲贊 0 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章