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這個函數接口。使客戶程序容易瞭解到想要做什麼,應該告訴郵局什麼內容,郵局才能正確的工作。
目前爲止,還都是比較簡單的模式,越到後面越複雜。我的理解是當沒有模式的時候,大家編寫代碼也需要考慮擴展性、伸縮性、穩定性等等。那個時候大家寫程序都是自己在摸索經驗,逐漸的才意識到程序應該可以適應需求的變化。於是總結很多方法來,讓程序既能適應變化,又有一定的可靠性。這使得編程序更有趣,也更抽象了。所以軟件開發就是提煉和抽象的過程。類似於哲學的提煉,從特殊到一般。