代碼不重要,重要的是這個思想微信
說白了就是想作到想 註釋中間件同樣,存在的時候,全局都會走那個中間件,不要用的時候註釋掉,除了不實現那個功能以外對全局都不會有影響。函數
這就是可插拔式設計。設計
首先講解一個模塊 importlibcode
這個模塊的做用:以字符串的形式導入模塊中間件
module = 'file.a' importlib.import_module(module) 上面這句就等於下面這句 from file import a
接下來就能夠講一下可插拔式設計了。對象
如今我想有三種通知方式,短信通知,郵件通知,微信通知,並且我想禁用哪一個,就直接禁用哪一個,而不用經過去方法裏面一個個的註釋掉這個函數。blog
首先建一個包notify,包裏面有四個py文件,init.py email.py msg.py wechat.py字符串
而後在根目錄下寫兩個py文件 ,一個是 run.py 一個是settings.pyget
settings.pyit
NOTYFY_LIST = [ 'notify.email.Email', 'notify.msg.Msg', 'notify.wechat.WeChat', ]
run.py
import notify notify.send_all('hahahaahaha')
email.py
class Email(): def __init__(self): pass def send(self,content): print('郵件通知:%s'%content)
msg.py
class Msg(): def __init__(self): pass def send(self,content): print('短信通知:%s'%content)
wechat.py
class WeChat(): def __init__(self): pass def send(self,content): print('vx通知:%s'%content)
最重要的一個py文件
import settings import importlib def send_all(content): for module_path in settings.NOTYFY_LIST: module, class_name = module_path.rsplit('.',maxsplit=1) mod = importlib.import_module(module) # 上面這句等於from notify import email cls = getattr(mod,class_name) #利用反射獲取模塊種類的變量名 obj = cls() obj.send(content)
整體講解:
首先寫一個文件夾notify,在這個文件夾裏面寫了三個py文件,分別用面向對象的方式在每一個文件裏面寫了三個通知的類,每一個類都有一個send方法,用來被調用。而後去settings文件裏面把這三個類的路徑以字符串的形式配置好。
而後,最重要的一步開始了,在notify文件夾裏寫了一個__init__.py文件,這就讓這個文件夾變成了包。導入這個包的東西,就只用導入這個init就行。前提是在init裏面吧那三個py文件導入了先。
在init 裏導入了settings裏的配置好的字符串路徑,循環這個字符串列表,而後經過這句module, class_name = module_path.rsplit('.',maxsplit=1) 切片,module拿到的就是notify.email ,class_name拿到的就是Email
而後經過importlib.import_module(module),獲得的結果就是那個模塊,在這裏也就是email模塊。 而後又經過反射,獲取在這個模塊裏的類的變量名,用cls來接收,循環的第一次就是 Email這個類,而後obj = cls()實例化生成了一個對象,obj.send(content)就執行了他的方法,打印了一條結果,settings裏配置了幾個,就打印幾個結果。固然咱們要運行的文件是 run文件,run裏面就只用導入這個包,就至關於導入了這個包的 init 文件,直接notify.send_all('輸出我要輸入的字符') 就好了。
這樣一來就實現了可插拔式設計,代碼不重要,重要的是這個思想。