不寫垃圾程式碼,從學會這個設計模式開始
大家好,我們今天來一起學習一個新的設計模式,叫做媒介模式。
所謂的媒介其實是一種封裝的思想,把某些功能共同的邏輯抽象出來做成一箇中間的媒介,從而減少程式碼之間的耦合,提升拓展性,更加方便日後的需求變更。
簡單案例
我們用一個實際的例子來認知一下媒介這個設計模式。
假設我們要做一個聊天室,如果真要去做的話,這裡面會非常複雜,涉及到很多網路程式設計的知識,比如廣播、客戶端、服務端等等。為了方便演示,我們把這些都簡化了。這樣簡化到極致之後,我們的聊天室程式碼就只有幾行:
class User:
def __init__(self, name):
self.name = name
def say(self, message):
call_something()
print('[{} says:] {}'.format(self.name, message))
這段邏輯沒什麼好說的,大家應該都能看懂。假設我們就這麼完成了產品經理的需求,會有一個什麼問題呢?
功能上當然是OK的,但是系統設計上有兩個比較大的問題。第一個是邏輯重複的問題,我們在User也就是聊天室中使用者物件的類當中實現了怎麼在聊天室當中聊天的功能。我們會發現使用者之間的私聊,使用者之間的視訊、語言等可能都會用到差不多的邏輯,比如建立網路連線,比如傳送訊息,判斷訊息是否傳送成功等等。
但是現在這些邏輯是寫死在User這個類裡了,如果其他類想要使用,根本沒法複用,只能把程式碼拷貝一份。這樣拷貝來拷貝去就會使得程式碼變得非常混亂,變得難以維護。
第二個問題是邏輯耦合的問題,User這個類是聊天室的使用者物件類,但是其中實現了很多聊天室的功能。表面上看是簡單了,但其實是聊天室和使用者這兩個不同概念的程式碼耦合在一起了。很多垃圾專案都有這個問題,明明A本身就應該是一個單獨的實體,結果我卻需要去修改B當中的程式碼。時間一長,連開發者自己都會忘記當初實現某某的邏輯放在哪裡。
通過對這個案例的分析,其實也是對為什麼要使用設計模式這個問題的回答。設計模式大多數情況下並不能直接提升專案的執行效率,它最大的功能是為了程式碼的拓展性以及可維護性。如果不使用合理的設計模式,隨著功能的增多,專案程式碼和逐漸變得越來越臃腫,直到人類難以維護的地步。
媒介模式
迴歸正題,那麼我們怎麼樣來使用媒介設計模式來解決上面的這兩個問題呢?
其實很簡單,我們直接來看程式碼吧:
class ChatRoom:
def display_message(self, user, message):
print('[{} says]: {}'.format(user, message))
class User:
def __init__(self, name):
self.name = name
self.chat_room = ChatRoom()
def say(self, message):
self.chat_room.display_message(self, message)
也就是說我們抽象出了一個ChatRoom這個類,將聊天室的功能從User類當中剝離了出去,並且將它作為了User類的一個成員變數。這樣做的好處是,當以後聊天室的功能需要複用或者是需要修改的時候,我們可以避免對User類的打擾。不然的話,開發人員需要在User類的一堆程式碼當中準確找到聊天室的相關邏輯進行修改,相信我,這絕不是什麼很好的體驗。
當然,到這裡並沒有優化到極致,由於User這個類的例項很多,我們會發現每次我們建立一個User的例項都會產生一個ChatRoom的例項,這其實是非常多餘並且沒有必要的。所以我們可以把ChatRoom設計成單例模式,不管User建立多少例項,獲得的ChatRoom都是同一個,這樣就節省了記憶體開銷。
我們用單例模式來改寫一下ChatRoom的程式碼:
import threading
class ChatRoom:
_lock = threading.Lock()
def __init__(self):
pass
def __new__(cls, *algs, **kw):
if not hasattr(ChatRoom, '_instance'):
with ChatRoom._lock:
if not hasattr(ChatRoom, '_instance'):
ChatRoom._instance = object.__new__(cls)
return ChatRoom._instance
到這裡,這個問題才算是被優化到了極限。看似很簡單的一個功能,其實當中涉及的細節和思考還是很多的,絕不是表面上看起來的那麼簡單,這些內容書本上往往是學不到的,只能通過自己的實踐和思考來獲得。
今天的文章就到這裡,衷心祝願大家每天都有所收穫。如果還喜歡今天的內容的話,請來一個三連支援吧~(點贊、關注、轉發)