python-訪問者模式

源碼地址:https://github.com/weilanhanf/PythonDesignPatterns

?

說明:

訪問者模式的基本想法是,軟件系統中擁有一個由許多對象構成的、比較穩定的對象結構,這些對象的類都擁有一個 accept 方法用來接受訪問者對象的訪問。訪問者是一個接口,它擁有一個 visit 方法,這個方法對訪問到的對象結構中不同類型的元素做出不同的處理。在對象結構的一次訪問過程中,我們遍歷整個對象結構,對每一個元素都實施 accept 方法,在每一個元素的 accept 方法中會調用訪問者的 visit 方法,從而使訪問者得以處理對象結構的每一個元素,我們可以針對對象結構設計不同的訪問者類來完成不同的操作,達到區別對待的效果。

訪問者模式定義:封裝一些作用于某種數據結構中的各元素的操作,它可以在不改變這個數據結構的前提下定義作用于這些元素的新的操作。

?

結構:

抽象訪問者,具體訪問者,抽象元素,具體元素,對象結構。

實例:

假設一個藥房,有一些大夫,一個藥品劃價員和一個藥房管理員,它們通過一個藥房管理系統組織工作流程。大夫開出藥方后,藥品劃價員確定藥品是否正常,價格是否正確;通過后藥房管理員進行開藥處理。該系統可以如何實現?最簡單的想法,是分別用一個一個if…else…把劃價員處理流程和藥房管理流程實現,這樣做的問題在于,擴展性不強,而且單一性不強,一旦有新藥的加入或者劃價流程、開藥流程有些變動,會牽扯比較多的改動。

#構造藥品類和工作人員類
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方法,其參數是個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

優點:

符合單一指責,凡是適用訪問者模式的場景中,元素類中需要封裝在訪問者中的操作必定是與元素類本身關系不大且是易變的操作,使用訪問者模式一方面符合單一職責原則,另一方面,因為被封裝的操作通常來說都是易變的,所以當發生變化時,就可以在不改變元素類本身的前提下,實現對變化部分的擴展。擴展性良好,元素類可以通過接受不同的訪問者來實現對不同操作的擴展。

缺點:

增加新的元素類很困難。在訪問者模式中,每增加一個新的元素類都意味著要在抽象訪問者角色中增加一個新的抽象操作,并在每一個具體訪問者類中增加相應的具體操作,違背了“開閉原則”的要求。破壞封裝。當采用訪問者模式的時候,就會打破組合類的封裝。

使用場景:

對象結構中對象對應的類很少改變,但經常需要在此對象結構上定義新的操作。需要對一個對象結構中的對象進行很多不同的并且不相關的操作,而需要避免讓這些操作“污染”這些對象的類,也不希望在增加新操作時修改這些類。

?

轉載于:https://www.cnblogs.com/welan/p/9130622.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/451567.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/451567.shtml
英文地址,請注明出處:http://en.pswp.cn/news/451567.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

面試題:Fibonacci數列

題目描述:大家都知道斐波那契數列,現在要求輸入一個整數n,請你輸出斐波那契數列的第n項(從0開始,第0項為0)。 方法1:遞歸 public class Solution {public int Fibonacci(int n) {if (n 0){retu…

“行到水窮處,坐看云起時.“

前些天發現了一個巨牛的人工智能學習網站,通俗易懂,風趣幽默,忍不住分享一下給大家。點擊跳轉到教程。 自由自在,隨意而行, 只沿著流水向上,不知不覺的就走到了泉眼盡頭, 無路可走的時候 &…

git commit -m和git commit -am

字面解釋的話,git commit -m用于提交暫存區的文件;git commit -am用于提交跟蹤過的文件 要理解它們的區別,首先要明白git的文件狀態變化周期,如下圖所示 工作目錄下面的所有文件都不外乎這兩種狀態:已跟蹤或未跟蹤。已…

磁盤結構簡介

這里講的主要是網上所謂的老式磁盤,它是由一個個盤片組成的,我們先從個盤片結構講起。如圖1所示,圖中的一圈圈灰色同心圓為一條條磁道,從圓心向外畫直線,可以將磁道劃分為若干個弧段,每個磁道上一個弧段被稱…

java中的對象監視器

參考文章:監視器–JAVA同步基本概念 感謝作者分享!

Yii1.1 CGridView 簡單使用

Yii1.1 CGridView 簡單使用 配置model文件,返回CActiveDataProvider對象。public function search() {$criterianew CDbCriteria;$criteria->compare(title,$this->title,true);$criteria->compare(type,$this->type);$criteria->compare(addr,$this…

3個著名加密算法(MD5、RSA、DES)的解析

MD5的全稱是Message-Digest Algorithm 5,在90年代初由MIT的計算機科學實驗室和RSA Data Security Inc發明,經MD2、MD3和MD4發展而來。 MD5將任意長度的“字節串”變換成一個128bit的大整數,并且它是一個不可逆的字符串變換算法&#x…

想念我的大大的石

前些天發現了一個巨牛的人工智能學習網站,通俗易懂,風趣幽默,忍不住分享一下給大家。點擊跳轉到教程。 // ------- 甘愿用我的一生去追尋 ... 想念我的大石頭: 想念會默默陪著我,一直從烈日咫尺坐到黃昏浸透蔓蔓云層…

Java 中的悲觀鎖、樂觀鎖、自旋鎖、適應性自旋鎖、偏向鎖、輕量級鎖、重量級鎖、公平鎖、非公平鎖、可重入鎖、共享鎖等

參考文獻: 不可不說的Java“鎖”事 java并發進階 感謝美團技術團隊! 感謝JavaGuide!

Git 的origin和master解析

首先要明確一點,對git的操作是圍繞3個大的步驟來展開的(其實幾乎所有的SCM都是這樣) 1. 從git取數據(git clone) 2. 改動代碼 3. 將改動傳回git(git push) 這3個步驟又涉及到兩個re…

end to end testing

概念 https://www.softwaretestinghelp.com/what-is-end-to-end-testing/ What is “End to End Testing”? Term “End to End testing” is defined as a testing method which determines whether the performance of an application is as per the requirement or not. It…

windows下安裝mysql 開機啟動

1 下載地址 http://dev.mysql.com/downloads/installer/ 2 下載版本 mysql community server 5.7.x 這個版本是一個傻瓜版本,設置root密碼之后就可以啟動服務了,不用自己配置,還有workbench可用。轉載于:https://www.cnblogs.com/hustdc/p/91…

Linux目錄架構詳解

Linux和Windows操作系統的顯著區別之一就是目錄架構的不同。Linux操作系統的目錄架構遵循文件系統層級結構標準。不知你是否使用ls命令瀏覽過Linux的根目錄“/”,親愛的讀者,您都了解這些目錄的含義嗎? ls -l / 遍歷文件系統(點擊…

越陽光明媚....

前些天發現了一個巨牛的人工智能學習網站,通俗易懂,風趣幽默,忍不住分享一下給大家。點擊跳轉到教程。 窗外陽光明媚,而心卻如此哀傷... 很喜歡陽光明媚,很喜歡春暖花開, 窗外有幾片莊稼地:滿…

Linux的學習:

查看端口: netstat -anop | grep 80 netstat -ntlp 先看看不帶n的 再看看帶n的 我們發現在local address 即主機地址這一欄中,如果沒有帶n選項,會將套接字所對應的域名解析出來,如果加上n選項,那么就不會顯示&#xff…

基于TCP協議的Socket通信

參考文章: Socket學習網絡基礎準備 基于TCP協議的Socket通信(1) 基于TCP協議的Socket通信(2) 感謝菜鳥分享!

git pull命令

git pull命令作用:從另一個存儲庫或本地分支關聯的遠端分支獲取最新代碼,并與本地代碼資源整合。git pull命令執行過程:取回遠程主機某個分支的更新,再與本地的指定分支合并(可能存在需手動解決的沖突)。 …

RPM的用法

RPM 有五種基本的操作方式(不包括創建軟件包): 安裝, 卸載, 升級, 查詢,和驗證。 下面我們就來逐一的講解吧。 一、 安裝RPM包 RPM 軟件包通常具有類似foo-1.0-1.i386.rpm 的文件名。其中包括 軟件包的名稱(foo),版本號(1.0),發行號(1), 和 硬…

Unix 多進程編程

一.多進程程序的特點由于UNIX系統是分時多用戶系統, CPU按時間片分配給各個用戶使用, 而在實質上應該說CPU按時間片分配給各個進程使用, 每個進程都有自己的運行環境以使得在CPU做進程切換時不會"忘記"該進程已計算了一半的"半成品". 以DOS的概念來說, 進程…

Redis單線程模型是什么?

參考文章: redis 單線程的理解 謝謝作者分享!