如何喫到回鍋肉?找廚師啊——外觀模式實例解析

好不容易盼到週末啦!Jungle想喫點好的犒勞自己!喫什麼呢?回鍋肉!是的,喫回鍋肉!

可是這過程好麻煩啊,先得去市場裏買肉,買回來得洗好,然後切好,再炒肉,最後才能喫上!不僅過程繁雜,而且Jungle還得跟市場、廚房打交道,想想都頭大。

如果有個廚師就好了,Jungle直接告訴廚師“我要喫回鍋肉”,20分鐘後廚師直接端上來就開喫。而中間那些買肉洗肉切肉的過程Jungle統統不關心了,而且Jungle也不必再關心市場和廚房,直接和廚師說句話就ok!真是方便!

 在這個例子中,廚師整合了一系列複雜的過程,外界(Jungle)只需與廚師交互即可。在軟件設計模式中,有一類設計模式正式如此——外觀模式。

1.外觀模式簡介

外觀模式是一種使用頻率較高的設計模式,它提供一個外觀角色封裝多個複雜的子系統,簡化客戶端與子系統之間的交互,方便客戶端使用。外觀模式可以降低系統的耦合度。如果沒有外觀類,不同的客戶端在需要和多個不同的子系統交互,系統中將存在複雜的引用關係,如下圖。引入了外觀類,原有的複雜的引用關係都由外觀類實現,不同的客戶端只需要與外觀類交互。

外觀模式:

爲子系統中的一組接口提供一個統一的入口。外觀模式定義了一個高層接口,這個接口使得這一子系統更加容易使用。

 外觀模式的應用很多,比如瀏覽器,用戶要查找什麼東西,不論是瀏覽知乎、騰訊或者CSDN,用戶都只需要打開瀏覽器即可,剩下的搜索工作由瀏覽器完成。

2.外觀模式結構

外觀模式的UML結構圖如下所示:

外觀模式一共有以下角色:

  • Facade(外觀角色):外觀角色可以知道多個相關子系統的功能,它將所有從客戶端發來的請求委派給相應的子系統,傳遞給相應的子系統處理。
  • SubSystem(子系統角色):子系統是一個類,或者由多個類組成的類的集合,它實現子系統具體的功能。 

3.外觀模式代碼實例

電腦主機(Mainframe)中只需要按下主機的開機按鈕(powerOn),即可調用其他硬件設備和軟件的啓動方法,如內存(Memory)的自檢(selfCheck)、CPU的運行(run)、硬盤(HardDisk)的讀取(read)、操作系統(OS)的載入(load)等。如果某一過程發生錯誤則電腦開機失敗。

這裏Jungle用外觀模式來模擬該過程,該例子UML圖如下:

3.1.子系統類

本例中一共有4個子系統,因此設計4個類:Memory、CPU、HardDisk和OS,並且每個子系統都有自己獨立的流程。

//子系統:內存
class Memory
{
public:
	Memory(){}
	void selfCheck(){
		printf("…………內存自檢……\n");
	}
};

//子系統:CPU
class CPU
{
public:
	CPU(){}
	void run(){
		printf("…………運行CPU運行……\n");
	}
};

//子系統:硬盤
class HardDisk
{
public:
	HardDisk(){}
	void read(){
		printf("…………讀取硬盤……\n");
	}
};

//子系統:操作系統
class OS
{
public:
	OS(){}
	void load(){
		printf("…………載入操作系統……\n");
	}
};

3.2.外觀類設計

//外觀類
class Facade
{
public:
	Facade(){
		memory = new Memory();
		cpu = new CPU();
		hardDisk = new HardDisk();
		os = new OS();
	}
	void powerOn(){
		printf("正在開機……\n");
		memory->selfCheck();
		cpu->run();
		hardDisk->read();
		os->load();
		printf("開機完成!\n");
	}
private:
	Memory *memory;
	CPU *cpu;
	HardDisk *hardDisk;
	OS *os;
};

3.3.客戶端代碼示例

#include <iostream>
#include "FacadePattern.h"

int main()
{
	Facade *facade = new Facade();
	facade->powerOn();

	printf("\n\n");

	system("pause");
	return 0;
}

看到了嗎,客戶端的代碼就是如此簡單,跟子系統無關! 

3.4.效果

4.總結

優點:

  • 外觀模式使得客戶端不必關心子系統組件,減少了與客戶端交互的對象的數量,簡化了客戶端的編程;
  • 外觀模式可以大大降低系統的耦合度;
  • 子系統的變化並不需要修改客戶端,只需要適當修改外觀類即可;
  • 子系統之間不會相互影響。

缺點:

  • 如果需要增加或者減少子系統,需要修改外觀類,違反開閉原則
  • 並不能限制客戶端直接與子系統交互,但如果加強限制,又使得系統靈活度降低。

適用場景:

  • 爲訪問一系列複雜的子系統提供一個統一的、簡單的入口,可以使用外觀模式;
  • 客戶端與多個子系統之間存在很大依賴,但在客戶端編程,又會增加系統耦合度,且使客戶端編程複雜,可以使用外觀模式。

歡迎關注知乎專欄:Jungle是一個用Qt的工業Robot

歡迎關注Jungle的微信公衆號:Jungle筆記

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章