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这个函数接口。使客户程序容易了解到想要做什么,应该告诉邮局什么内容,邮局才能正确的工作。

目前为止,还都是比较简单的模式,越到后面越复杂。我的理解是当没有模式的时候,大家编写代码也需要考虑扩展性、伸缩性、稳定性等等。那个时候大家写程序都是自己在摸索经验,逐渐的才意识到程序应该可以适应需求的变化。于是总结很多方法来,让程序既能适应变化,又有一定的可靠性。这使得编程序更有趣,也更抽象了。所以软件开发就是提炼和抽象的过程。类似于哲学的提炼,从特殊到一般。

posted on 2011-04-12 22:23  星晨_jqren  阅读(8743)  评论(3编辑  收藏  举报