前言 模式介紹 外觀模式相比較之下比較簡單,模式設計中定義是為子系統中的一組介面提供一個一致的界面,此模式定義了一個高層介面,這個介面是的這一子系統更加容易使用。 如果不理解呢,簡單些說就是外觀模式提供了為內部提供了同意的介面層,解耦了子系統和客戶端,這樣客戶端只需要知道外觀類存在即可,不需要知道具 ...
前言
模式介紹
外觀模式相比較之下比較簡單,模式設計中定義是為子系統中的一組介面提供一個一致的界面,此模式定義了一個高層介面,這個介面是的這一子系統更加容易使用。
如果不理解呢,簡單些說就是外觀模式提供了為內部提供了同意的介面層,解耦了子系統和客戶端,這樣客戶端只需要知道外觀類存在即可,不需要知道具體子系統是如何實現的。舉一個簡單的例子,海參面館中兩個主打麵食是:
海參炒麵
辣根湯麵
兩個主打麵食都由一個師傅來做,這個師傅會這兩種麵食的做法。具體的做法呢如下:
- 海參炒麵
1. 剝蒜
2. 拉麵
3. 做湯底
- 辣根湯麵
1. 製作辣根
這兩種麵食都有複雜的做法,調用者如果直接調用這種步驟,會讓調用者與師傅的耦合性很高,如果有一天製作步驟改了,辣根湯麵要剝蒜,那就需要修改調用者介面,這樣是不可以的。
所以這時候師傅就是一個外觀類,調用者只需要和他說,我需要一份海參炒麵或者辣根湯麵即可,具體如何做,就是師傅的事情了。外部不需要管。UML類圖如下:
UML類圖
代碼實例
下麵是剝蒜類實現,非常簡單,只完成剝蒜動作即可。
#ifndef GRALIC_H
#define GRALIC_H
class gralic
{
public:
gralic();
~gralic();
public:
void peelinggralic();
};
#endif // GRALIC_H
#include <iostream>
#include "gralic.h"
gralic::gralic()
{
}
gralic::~gralic()
{
}
void gralic::peelinggralic()
{
std::cout << "開始剝蒜啦!!!" << std::endl;
}
下麵是拉麵類實現,只實現拉麵動作即可。
#ifndef NOODLE_H
#define NOODLE_H
class noodle
{
public:
noodle();
~noodle();
public:
void makenoodle();
};
#endif // NOODLE_H
#include <iostream>
#include "noodle.h"
noodle::noodle()
{
}
noodle::~noodle()
{
}
void noodle::makenoodle()
{
std::cout << "開始拉麵啦!!!" << std::endl;
}
其餘子系統類似,就不在此展示了,包括:做湯底類和製作辣根類。
下麵是外觀模式,廚師師傅類,包含兩個介面:製作海參炒麵和辣根湯麵。但是實現部分是使用各個子系統中的類和介面完成的,完成了客戶端調用的解耦動作。
#ifndef COOKERFACADE_H
#define COOKERFACADE_H
class gralic;
class noodle;
class soup;
class lagen;
class cookerfacade
{
public:
cookerfacade();
~cookerfacade();
public:
void makehaishennoodle();
void makelagennoodle();
private:
gralic *m_gra;
noodle *m_noo;
soup *m_so;
lagen *m_lg;
};
#endif // COOKERFACADE_H
#include <iostream>
#include "cookerfacade.h"
#include "gralic.h"
#include "noodle.h"
#include "soup.h"
#include "lagen.h"
cookerfacade::cookerfacade()
{
m_gra = new gralic();
m_noo = new noodle();
m_so = new soup();
m_lg = new lagen();
}
cookerfacade::~cookerfacade()
{
delete m_gra; m_gra = NULL;
delete m_noo; m_noo = NULL;
delete m_so; m_so = NULL;
delete m_lg; m_lg = NULL;
}
void cookerfacade::makehaishennoodle()
{
m_gra->peelinggralic();
m_noo->makenoodle();
m_so->makesoup();
std::cout << "開始做海參炒麵啦!!!" << std::endl;
}
void cookerfacade::makelagennoodle()
{
m_lg->makelagen();
std::cout << "開始作辣根湯麵啦!!!" << std::endl;
}
下麵是客戶端代碼,可以很明顯的看出他只需要知道外觀師傅的類即可,別的細節並不需要知道。
#include <iostream>
#include "cookerfacade.h"
using namespace std;
int main()
{
cookerfacade *cf = new cookerfacade();
cout << "老闆,來一份辣根湯麵!!!" << endl;
cf->makelagennoodle();
cout << "老闆,換一份海參炒麵!!!" << endl;
cf->makehaishennoodle();
return 0;
}
下麵是編譯需要的CMakeLists.txt文件:
cmake_minimum_required(VERSION 2.8)
project(cooker-facade)
set(SRC_LIST main.cpp soup.h soup.cpp gralic.h gralic.cpp cookerfacade.h cookerfacade.cpp noodle.h noodle.cpp
lagen.h lagen.cpp)
add_executable(${PROJECT_NAME} ${SRC_LIST})
編譯運行結果
外觀模式的源代碼下載位置是:https://github.com/erguangqiang/freesir_headfirst/blob/master/cooker-facade.tar.gz
代碼運行的結果如下:
blog@blog-VirtualBox:~/build-cooker-facade-unknown-Default$ ./cooker-facade
老闆,來一份辣根湯麵!!!
開始製作辣根!!!
開始作辣根湯麵啦!!!
老闆,換一份海參炒麵!!!
開始剝蒜啦!!!
開始拉麵啦!!!
開始做湯底啦!!!
開始做海參炒麵啦!!!
結束語
其實外觀模式我們可能一直在用,只是我們不知道自己在用外觀模式而已,平時我們開發一個系統的時候,對外API完全封裝內部子系統介面,以達到便於擴展可維護的目的,其實用的就是外觀模式。這種模式可以充分解耦客戶端和子系統。同時也是應用比較廣比較簡單的設計模式。