18、Python與設計模式–訪問者模式
一、藥房業務系統
假設一個藥房,有一些大夫,一個藥品劃價員和一個藥房管理員,它們通過一個藥房管理系統組織工作流程。大夫開出藥方後,藥品劃價員確定藥品是否正常,價格是否正確;通過後藥房管理員進行開藥處理。該系統可以如何實現?最簡單的想法,是分別用一個一個if…else…把劃價員處理流程和藥房管理流程實現,這樣做的問題在於,擴充套件性不強,而且單一性不強,一旦有新藥的加入或者劃價流程、開藥流程有些變動,會牽扯比較多的改動。今天介紹一種解決這類問題的模式:訪問者模式。
首先,構造藥品類和工作人員類:
class Medicine:
name=""
price=0.0
def __init__(self,name,price):
self.name=name
self.price=price
def getName(self):
return self.name
def setName(self,name):
self.name=name
def getPrice(self):
return self.price
def setPrice(self,price):
self.price=price
def accept(self,visitor):
pass
class Antibiotic(Medicine):
def accept(self,visitor):
visitor.visit(self)
class Coldrex(Medicine):
def accept(self,visitor):
visitor.visit(self)
藥品類中有兩個子類,抗生素和感冒藥;
class Visitor:
name=""
def setName(self,name):
self.name=name
def visit(self,medicine):
pass
class Charger(Visitor):
def visit(self,medicine):
print "CHARGE: %s lists the Medicine %s. Price:%s " % (self.name,medicine.getName(),medicine.getPrice())
class Pharmacy(Visitor):
def visit(self,medicine):
print "PHARMACY:%s offers the Medicine %s. Price:%s" % (self.name,medicine.getName(),medicine.getPrice())
工作人員分為劃價員和藥房管理員。
在藥品類中,有一個accept方法,其引數是個visitor;而工作人員就是從Visitor類中繼承而來的,也就是說,他們就是Visitor,都包含一個visit方法,其引數又恰是medicine。藥品作為處理元素,依次允許(Accept)Visitor對其進行操作,這就好比是一條流水線上的一個個工人,對產品進行一次次的加工。整個業務流程還差一步,即藥方類的構建(流水線大機器)。
class ObjectStructure:
pass
class Prescription(ObjectStructure):
medicines=[]
def addMedicine(self,medicine):
self.medicines.append(medicine)
def rmvMedicine(self,medicine):
self.medicines.append(medicine)
def visit(self,visitor):
for medc in self.medicines:
medc.accept(visitor)
藥方類將待處理藥品進行整理,並組織Visitor依次處理。
業務程式碼如下:
if __name__=="__main__":
yinqiao_pill=Coldrex("Yinqiao Pill",2.0)
penicillin=Antibiotic("Penicillin",3.0)
doctor_prsrp=Prescription()
doctor_prsrp.addMedicine(yinqiao_pill)
doctor_prsrp.addMedicine(penicillin)
charger=Charger()
charger.setName("Doctor Strange")
pharmacy=Pharmacy()
pharmacy.setName("Doctor Wei")
doctor_prsrp.visit(charger)
doctor_prsrp.visit(pharmacy)
列印如下:
CHARGE: Doctor Strange lists the Medicine Yinqiao Pill. Price:2.0
CHARGE: Doctor Strange lists the Medicine Penicillin. Price:3.0
PHARMACY:Doctor Wei offers the Medicine Yinqiao Pill. Price:2.0
PHARMACY:Doctor Wei offers the Medicine Penicillin. Price:3.0
二、訪問者模式
訪問者模式的定義如下:封裝一些作用於某種資料結構中的各元素的操作,它可以在不改變資料結構的前提下定義於作用於這些元素的新操作。
提到訪問者模式,就不得不提一下雙分派。分派分為靜態分派和動態分派。首先解釋下靜態分派,靜態分派即根據請求者的名稱和接收到的引數,決定多型時處理的操作。比如在Java或者C++中,定義名稱相同但引數不同的函式時,會根據最終輸入的引數來決定呼叫哪個函式。雙分派顧名思義,即最終的操作決定於兩個接收者的型別,在本例中,藥品和工作人員互相呼叫了對方(藥品的accept和工作人員的visit中,對方都是引數),就是雙分派的一種應用。
那麼Python支援靜態分派麼?先看下面的一個例子。
def max_num(x,y,z):
return max(max(x,y),z)
def max_num(x,y):
return max(x,y)
if __name__=="__main__":
print max_num(1,2,4)
列印如下:
Traceback (most recent call last):
File “D:/WorkSpace/Project/PyDesignMode/example.py”, line 786, in
print max_num(1,2,4)
TypeError: max_num() takes exactly 2 arguments (3 given)
可見,Python原生是不支援靜態分派的,因而也不直接支援更高層次的分派。訪問者模式實現的分派,是一種動態雙分派。但這並不妨礙Python通過訪問者模式實現一種基於類的“雙分派效果”。Python多分派可以參考David Mertz 博士的一篇文章:可愛的Python:多分派—用多元法泛化多樣性。
三、訪問者模式的優點和應用場景
優點:
1、將不同的職責非常明確地分離開來,符合單一職責原則;
2、職責的分開也直接導致擴充套件非常優良,靈活性非常高,加減元素和訪問者都非常容易。
應用場景:
1、要遍歷不同的物件,根據物件進行不同的操作的場景;或者一個物件被多個不同物件順次處理的情況,可以考慮使用訪問者模式。除本例外,報表生成器也可以使用訪問者模式實現,報表的資料來源由多個不同的物件提供,每個物件都是Visitor,報表這個Element順次Accept各訪問者完善並生成物件。
四、訪問者模式的缺點
1、訪問者得知了元素細節,與最小隔離原則相悖;
2、元素變更依舊可能引起Visitor的修改。
相關文章
- 設計模式:訪問者模式設計模式
- 設計模式(十六)——訪問者模式設計模式
- 「補課」進行時:設計模式(18)——訪問者模式設計模式
- 極簡設計模式-訪問者模式設計模式
- JAVA設計模式之訪問者模式Java設計模式
- 設計模式解密(22)- 訪問者模式設計模式解密
- PHP設計模式之訪問者模式PHP設計模式
- 設計模式學習之訪問者模式設計模式
- 設計模式 - ASM 中的訪問者模式設計模式ASM
- 【趣味設計模式系列】之【訪問者模式】設計模式
- C#設計模式之訪問者模式C#設計模式
- 23種設計模式之訪問者模式設計模式
- 15.java設計模式之訪問者模式Java設計模式
- 設計模式(二十):訪問者模式、迭代器模式、觀察者模式、原型模式、模板方法設計模式原型
- C#設計模式系列:訪問者模式(Visitor)C#設計模式
- 設計模式--訪問者模式Visitor(行為型)設計模式
- JAVA設計模式之 訪問者模式【Visitor Pattern】Java設計模式
- 15、Python與設計模式–中介者模式Python設計模式
- 設計模式(二十三)訪問者設計模式
- python-訪問者模式Python模式
- Java進階篇設計模式之十 ---- 訪問者模式和中介者模式Java設計模式
- 設計模式學習-使用go實現訪問者模式設計模式Go
- 設計模式的征途—16.訪問者(Visitor)模式設計模式
- Android理解設計模式之組合模式、迭代器模式、訪問者模式Android設計模式
- 訪問者模式模式
- 軟體設計模式學習(二十七)訪問者模式設計模式
- 軟體設計模式系列之二十五——訪問者模式設計模式
- Python 設計模式——觀察者模式Python設計模式
- Python設計模式-建造者模式Python設計模式
- Python設計模式-中介者模式Python設計模式
- Python設計模式-觀察者模式Python設計模式
- 行為模式-訪問者模式模式
- 18.java設計模式之中介者模式Java設計模式
- python設計模式之觀察者模式Python設計模式
- 通俗 Python 設計模式——建造者模式Python設計模式
- C++設計模式 - 訪問器模式(Visitor)C++設計模式
- 設計模式(python實現):觀察者模式設計模式Python
- 設計模式學習筆記(二十一)訪問者模式及其實現設計模式筆記