python-访问者模式
源碼地址:https://github.com/weilanhanf/PythonDesignPatterns
?
說明:
訪問者模式的基本想法是,軟件系統(tǒng)中擁有一個由許多對象構(gòu)成的、比較穩(wěn)定的對象結(jié)構(gòu),這些對象的類都擁有一個 accept 方法用來接受訪問者對象的訪問。訪問者是一個接口,它擁有一個 visit 方法,這個方法對訪問到的對象結(jié)構(gòu)中不同類型的元素做出不同的處理。在對象結(jié)構(gòu)的一次訪問過程中,我們遍歷整個對象結(jié)構(gòu),對每一個元素都實施 accept 方法,在每一個元素的 accept 方法中會調(diào)用訪問者的 visit 方法,從而使訪問者得以處理對象結(jié)構(gòu)的每一個元素,我們可以針對對象結(jié)構(gòu)設(shè)計不同的訪問者類來完成不同的操作,達到區(qū)別對待的效果。
訪問者模式定義:封裝一些作用于某種數(shù)據(jù)結(jié)構(gòu)中的各元素的操作,它可以在不改變這個數(shù)據(jù)結(jié)構(gòu)的前提下定義作用于這些元素的新的操作。
?
結(jié)構(gòu):
抽象訪問者,具體訪問者,抽象元素,具體元素,對象結(jié)構(gòu)。
實例:
假設(shè)一個藥房,有一些大夫,一個藥品劃價員和一個藥房管理員,它們通過一個藥房管理系統(tǒng)組織工作流程。大夫開出藥方后,藥品劃價員確定藥品是否正常,價格是否正確;通過后藥房管理員進行開藥處理。該系統(tǒng)可以如何實現(xiàn)?最簡單的想法,是分別用一個一個if…else…把劃價員處理流程和藥房管理流程實現(xiàn),這樣做的問題在于,擴展性不強,而且單一性不強,一旦有新藥的加入或者劃價流程、開藥流程有些變動,會牽扯比較多的改動。
#構(gòu)造藥品類和工作人員類 class Medicine:name=""price=0.0def __init__(self,name,price):self.name=nameself.price=pricedef getName(self):return self.namedef setName(self,name):self.name=namedef getPrice(self):return self.pricedef setPrice(self,price):self.price=pricedef 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=namedef 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方法,其參數(shù)是個visitor; 而工作人員就是從Visitor類中繼承而來的, 也就是說,他們就是Visitor,都包含一個visit方法,其參數(shù)又恰是medicine。 藥品作為處理元素,依次允許(Accept)Visitor對其進行操作, 這就好比是一條流水線上的一個個工人,對產(chǎn)品進行一次次的加工。 整個業(yè)務(wù)流程還差一步,即藥方類的構(gòu)建(流水線大機器) """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)打印結(jié)果:
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
優(yōu)點:
符合單一指責,凡是適用訪問者模式的場景中,元素類中需要封裝在訪問者中的操作必定是與元素類本身關(guān)系不大且是易變的操作,使用訪問者模式一方面符合單一職責原則,另一方面,因為被封裝的操作通常來說都是易變的,所以當發(fā)生變化時,就可以在不改變元素類本身的前提下,實現(xiàn)對變化部分的擴展。擴展性良好,元素類可以通過接受不同的訪問者來實現(xiàn)對不同操作的擴展。缺點:
增加新的元素類很困難。在訪問者模式中,每增加一個新的元素類都意味著要在抽象訪問者角色中增加一個新的抽象操作,并在每一個具體訪問者類中增加相應(yīng)的具體操作,違背了“開閉原則”的要求。破壞封裝。當采用訪問者模式的時候,就會打破組合類的封裝。使用場景:
對象結(jié)構(gòu)中對象對應(yīng)的類很少改變,但經(jīng)常需要在此對象結(jié)構(gòu)上定義新的操作。需要對一個對象結(jié)構(gòu)中的對象進行很多不同的并且不相關(guān)的操作,而需要避免讓這些操作“污染”這些對象的類,也不希望在增加新操作時修改這些類。?
轉(zhuǎn)載于:https://www.cnblogs.com/welan/p/9130622.html
總結(jié)
以上是生活随笔為你收集整理的python-访问者模式的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 阿里云 mysql 超时_mysql数据
- 下一篇: python tempfile clea