python設計模式之外觀模式

2022-01-23 14:29:44 字數 4640 閱讀 9458

系統會隨著演化變得非常複雜,最終形成大量的(並且有時是令人迷惑的)類和互動,這種情況並不少見。許多情況下,我們並不想把這種複雜性暴露給客戶端。外觀設計模式有助於隱藏系統的內部複雜性,並通過乙個簡化的介面向客戶端暴露必要的部分。本質上, 外觀( facade)是在已有複雜系統之上實現的乙個抽象層。

1. 現實生活中的例子

在現實中,外觀模式相當常見。當你致電乙個銀行或公司,通常是先被連線到客服部門,客服職員在你和業務部門(結算、技術支援、一般援助等)及幫你解決具體問題的職員之間充當乙個外觀的角色。

也可以將汽車或電單車的啟動鑰匙視為乙個外觀。外觀是啟用乙個系統的便捷方式,系統的內部則非常複雜。當然,對於其他可以通過乙個簡單按鈕就能啟用的複雜電子裝置,同樣可以如此看待,比如計算機。

2. 軟體的例子

django-oscar-datacash模組是django的乙個第三方元件,用於整合datacash支付閘道器。該元件有乙個gateway類,提供對多種datacash api的細粒度訪問。在那之上,它也包含乙個facade類,提供粗粒度api (提供給那些不需要處理細節的人),並針對審計目的提供儲存事務的能力。

caliendo是乙個用於模擬python api的的介面,它包含乙個facade模組。該模組使用外觀模式來完成許多不同但有用的事情(比如快取方法),並基於傳給頂層facade方法的輸入物件決定返回什麼方法。

3. 應用案例

使用外觀模式的最常見理由是為乙個複雜系統提供單個簡單的入口點。引入外觀之後,客戶端**通過簡單地呼叫乙個方法/函式就能使用乙個系統。同時,內部系統並不會丟失任何功能,外觀只是封裝了內部系統。

不把系統的內部功能暴露給客戶端**有乙個額外的好處:我們可以改變系統內部,但客戶端**不用關心這個改變,也不會受這個改變的影響。客戶端**不需要進行任何改變。

如果你的系統包含多層,外觀模式也能派上用場。你可以為每一層引入乙個外觀入口點,並讓所有層級通過它們的外觀相互通訊。這提高了層級之間的松耦合性,盡可能保持層級獨立。

假設我們想使用多服務程序方式實現乙個作業系統,類似於minix 3 那樣。多服務程序的作業系統有乙個極小的核心,稱為微核心( microkernel),它在特權模式下執行。系統的所有其他服務都遵從

一種服務架構(驅動程式伺服器、程序伺服器、檔案伺服器等)。每個服務程序屬於乙個不同的記憶體位址空間,以使用者模式在微核心之上執行。這種方式的優勢是作業系統更能容錯、更加可靠、更加安全。例如,由於所有驅動程式都以使用者模式在乙個驅動服務程序之上執行,所以某個驅動程式中的乙個bug並不能讓整個系統崩潰,也無法影響到其他服務程序。其劣勢則是效能開銷和系統程式設計的複雜性,因為服務程序和微核心之間,還有獨立的服務程序之間,使用訊息傳遞方式進行通訊。訊息傳遞比單核心(如linux)所使用的共享記憶體模型更加複雜。

我們從server介面①開始實現,使用乙個enum型別變數來描述乙個服務程序的不同狀態,使用abc模組來禁止對server介面直接進行初始化,並強制子類實現關鍵的boot()和kill()方法。這裡假設每個服務程序的啟動、關閉及重啟都相應地需要不同的動作。如果你以前沒用過abc模組,請記住以下幾個重要事項。

可隨意改變介面和方法簽名來滿足你的需求,但要確保在改變之後,客戶端**不需要知道operatingsystem外觀類之外的任何物件 完整**如下:

from enum import enum

from abc import abcmeta, abstractmethod

state = enum('state', 'new running sleeping restart zombie')

class user:

pass

class process:

pass

class file:

pass

class server(metaclass=abcmeta):

@abstractmethod

def __init__(self):

pass

def __str__(self):

return self.name

@abstractmethod

def boot(self):

pass

@abstractmethod

def kill(self, restart=true):

pass

class fileserver(server):

def __init__(self):

'''初始化檔案服務程序要求的操作'''

self.name = 'fileserver'

self.state = state.new

def boot(self):

print('booting the {}'.format(self))

'''啟動檔案服務程序要求的操作'''

self.state = state.running

def kill(self, restart=true):

print('killing {}'.format(self))

'''終止檔案服務程序要求的操作'''

self.state = state.restart if restart else state.zombie

def create_file(self, user, name, permissions):

'''檢查訪問許可權的有效性、使用者許可權等'''

print("trying to create the file '{}' for user '{}' with permissions

{}".format(name, user, permissions))

class processserver(server):

def __init__(self):

'''初始化程序服務程序要求的操作'''

self.name = 'processserver'

self.state = state.new

def boot(self):

print('booting the {}'.format(self))

'''啟動程序服務程序要求的操作'''

self.state = state.running

def kill(self, restart=true):

print('killing {}'.format(self))

'''終止程序服務程序要求的操作'''

self.state = state.restart if restart else state.zombie

def create_process(self, user, name):

'''檢查使用者許可權和生成pid等'''

print("trying to create the process '{}' for user '{}'".format(name, user))

class windowserver:

pass

class networkserver:

pass

class operatingsystem:

'''外觀'''

def __init__(self):

self.fs = fileserver()

self.ps = processserver()

def start(self):

[i.boot() for i in (self.fs, self.ps)]

def create_file(self, user, name, permissions):

return self.fs.create_file(user, name, permissions)

def create_process(self, user, name):

return self.ps.create_process(user, name)

def main():

os = operatingsystem()

os.start()

os.create_file('foo', 'hello', '-rw-r-r')

os.create_process('bar', 'ls /tmp')

if __name__ == '__main__':

main()

輸出如下:

booting the fileserver

booting the processserver

trying to create the file 'hello' for user 'foo' with permissions - rw-r-r

trying to create the process 'ls /tmp' for user 'bar'

外觀類operatingsystem起到了很好的作用。客戶端**可以建立檔案和程序,而無需知

道作業系統的內部細節,比如,多個服務程序的存在。準確點說是客戶端可以呼叫方法來建立文

件和程序,但是目前它們是模擬的。

5. 小結

本章中,我們學習了如何使用外觀模式。在客戶端**想要使用乙個複雜系統但又不關心系統複雜性之時,這種模式是為複雜系統提供乙個簡單介面的理想方式。一台計算機是乙個外觀,因為當我們使用它時需要做的事情僅是按乙個按鈕來啟動它;其餘的所有硬體複雜性都使用者無感知地交由bios、引導引導程式以及其他系統軟體來處理。現實生活中外觀的例子更多,比如,我們所致電的銀行或公司客服部門,還有啟動機動車所使用的鑰匙。

設計模式之外觀模式

外觀模式提供了乙個統一的介面,用來訪問子系統中的一群介面。這樣可以避免客戶端和子系統之間的緊耦合。這種模式需要將一系列的子系統組合到外觀中,然後將具體的工作交給各個子系統去完成。如此一來,可以簡化介面的呼叫。其本質就是將系統與客戶端互動的地方封裝起來。這個模式,總體來說,很簡單,理解起來也不困難。依...

設計模式之外觀模式

外觀模式 為子系統中的一組介面提供乙個一直的介面,此模式定義了乙個高層介面,這個介面使得這一子系統更加容易使用。即通過乙個中類來完成客戶端的請求。拿機房收費系統的上機過程來說,上機需要顯示上機者的資訊,填寫上機狀態表,填寫上機記錄表。而使用者不需要知道這些功能是怎麼實現的,只需要通過介面操作就可以完...

設計模式之外觀模式

外觀模式,為子系統中的一組介面提供乙個一致的介面,此模式定義了乙個高層介面,這個介面使得這一子系統更加容易使用。在設計初期階段,應該要有意識的將不同的兩個層分離,比如經典的三層架構,層與層之間建立外觀facade。在開發階段,子系統往往因不斷的重構演化而變得越來越複雜,增加外觀模式可以提供乙個簡單的...