訪問者模式,資料結構中儲存著許多元素,當改變一種對元素的處理方式但時,我們避免重複的修改資料類的結構,那我們在設計之初就將資料的處理分離,即資料類只提供乙個資料處理的介面,而資料類的處理方法我們叫它訪問者,那麼相同結構的資料面臨不同的處理結果時,我們只需要建立不同的訪問者。
我們假設一種場景:上市公司的原始財務資料,對於會計來說需要製作各種報表,對於財務總監來說需要分析公司業績,對於戰略顧問來說需要分析行業變化,我們來實現這一過程。
class finance:
"""財務資料結構類"""
def __init__(self):
self.salesvolume = none # 銷售額
self.cost = none # 成本
self.history_salesvolume = none # 歷史銷售額
self.history_cost = none # 歷史成本
def set_salesvolume(self, value):
self.salesvolume = value
def set_cost(self, value):
self.cost = value
def set_history_salesvolume(self, value):
self.history_salesvolume = value
def set_history_cost(self, value):
self.history_cost = value
def accept(self, visitor):
pass
class finance_year(finance):
"""2023年財務資料類"""
def __init__(self, year):
finance.__init__(self)
self.work = # 安排工作人員列表
self.year = year
def add_work(self, work):
def accept(self):
for obj in self.work:
obj.visit(self)
class accounting:
"""會計類"""
def __init__(self):
self.id = "會計"
self.duty = "計算報表"
def visit(self, table):
print('會計年度: {}'.format(table.year))
print("我的身份是: {} 職責: {}".format(self.id, self.duty))
print('本年度純利潤: {}'.format(table.salesvolume - table.cost))
print('------------------')
class audit:
"""財務總監類"""
def __init__(self):
self.id = "財務總監"
self.duty = "分析業績"
def visit(self, table):
print('會計總監年度: {}'.format(table.year))
print("我的身份是: {} 職責: {}".format(self.id, self.duty))
if table.salesvolume - table.cost > table.history_salesvolume - table.history_cost:
msg = "較同期**"
else:
msg = "較同期**"
print('本年度公司業績: {}'.format(msg))
print('------------------')
class adviser:
"""戰略顧問"""
def __init__(self):
self.id = "戰略顧問"
self.duty = "制定明年戰略"
def visit(self, table):
print('戰略顧問年度: {}'.format(table.year))
print("我的身份是: {} 職責: {}".format(self.id, self.duty))
if table.salesvolume > table.history_salesvolume:
msg = "行業上行,擴大生產規模"
else:
msg = "行業下行,減小生產規模"
print('本年度公司業績: {}'.format(msg))
print('------------------')
class work:
"""工作類"""
def __init__(self):
self.works = # 需要處理的年度資料列表
def add_work(self, obj):
def remove_work(self, obj):
self.works.remove(obj)
def visit(self):
for obj in self.works:
obj.accept()
if __name__ == '__main__':
work = work() # 計畫安排財務、總監、顧問對2023年資料處理
# 例項化2023年資料結構
finance_2018 = finance_year(2018)
finance_2018.set_salesvolume(200)
finance_2018.set_cost(100)
finance_2018.set_history_salesvolume(180)
finance_2018.set_history_cost(90)
accounting = accounting() # 例項化會計
audit = audit() # 例項化總監
adviser = adviser() # 例項化顧問
finance_2018.add_work(accounting) # 會計安排到2018分析日程中
finance_2018.add_work(audit) # 總監安排到2018分析日程中
finance_2018.add_work(adviser) # 顧問安排到2018分析日程中
work.add_work(finance_2018) # 新增2023年財務工作安排
work.visit()
會計年度: 2018
我的身份是: 會計 職責: 計算報表
本年度純利潤: 100
------------------
會計總監年度: 2018
我的身份是: 財務總監 職責: 分析業績
本年度公司業績: 較同期**
------------------
戰略顧問年度: 2018
我的身份是: 戰略顧問 職責: 制定明年戰略
本年度公司業績: 行業上行,擴大生產規模
------------------
上面年度可以實現:安排不同年份的財務報表給不同的角色分析,這就是訪問者模式的魅力;訪問者模式的核心是在保持原有資料結構的基礎上,實現多種資料的處理方法,該方法的角色就是訪問者。
訪問者模式作為常用設計模式中難度最大的一種模式,他的難度在於高度的抽象,及其多層巢狀,需要細心的品味。
設計模式 訪問者模式(二十三)
軟體領域中的設計模式的重要性不言而喻。設計模式中運用了物件導向程式設計語言的重要特性 封裝 繼承 多型。雖然知道這些特性的定義但是並沒有做到真正的理解,這樣特性有什麼作用?用於什麼場合中等等問題,帶著疑問開始學習設計模式,主要參考 大話設計模式 和 設計模式 可復用物件導向軟體的基礎 兩本書。訪問者...
設計模式二十三(訪問者模式)
訪問者模式 visitor 表示乙個作用於物件結構中的各個元素的操作。它使你可以在不改變各元素的類的前提下定義作用於這些元素的新操作 類圖的 訪問者模式的 如下 public abstract class visitor public class concretevisitor1 extends v...
小話設計模式(二十三)訪問者模式
訪問者的適用情況 1 乙個物件結構包含很多類物件,它們有不同的介面,而你想對這些物件實施一些依賴於其具體類的操作。2 需要對乙個物件結構中的物件進行很多不同的並且不想關的操作,而你想避免讓這些操作 汙染 這些物件的類。3 定義物件結構的類很少改變,但經常需要在此結構上定義新的操作。本文以遊戲中的倉庫...