模式例項之 訪問者例項

2021-09-05 22:25:21 字數 4792 閱讀 2829

場景:長途汽車票、火車票**調整

描述:春運開始了,**高峰期,打工的人群要回家過年了,票價要漲了!

1、抽象訪問者(

visitor

,程式中為:

notifyvisitor

)角色:宣告了乙個或者多個訪問操作,形成所有的具體元素角色必須實現的介面。 2

、具體訪問者(

concretevisitor

,程式中為各個期間的票價浮動情況)角色:實現抽象訪問者角色所宣告的介面,也就是抽象訪問者所宣告的各個訪問操作。 3

、抽象節點(

element

,程式中的交通工具基類)角色:宣告乙個接受操作,接受乙個訪問者物件作為乙個參量。 4

、具體節點(

concreteelement

,程式中的各類交通工具)角色:實現了抽象元素所規定的接受操作。 5

、結構物件(

obiectstructure

,程式中的交通管理部門)角色:有如下的一些責任,可以遍歷結構中的所有元素;如果需要,提供乙個高層次的介面讓訪問者物件可以訪問每乙個元素;如果需要,可以設計成乙個復合物件或者乙個聚集,如列(

list

)或集合(

set)。

在軟體構建過程中,由於需求的改變,某些類層次結構中常常需要增加新的行為(方法),如果直接在基類中做這樣的改變,將會給子類帶來很繁重的變更負擔,甚至破壞原有設計。

如何在不更改類層次結構的前提下,在執行時根據需要透明的為類層次結構上的各個類動態新增新的操作,從而避免上述問題?

標識乙個作用於某物件結構中的各元素的操作。它可以在不改變各元素的類的前提下定義作用於這些元素的新的操作。

實現1:在不使用訪問者的時候

(一)

交通工具標準 //

交通工具

public

abstract

class

vehicle

(二)長途汽車與火車

//bus

public

class

bus : vehicle

public

override

void pricefloatup()

} //train

public

class

train : vehicle

public

override

void pricefloatup()

} (三)測試

busbus = new

bus();

bus.showprice();

bus.pricefloatup();

train

train = new

train();

train.showprice();

train.pricefloatup();

結果:長途汽車石家莊到邢台50元

春運開始了,汽車票在原價的基礎上,上浮20%!

火車石家莊到邢台40元

春運開始了,火車票在原價的基礎上,上浮15%!

(四)特殊的日子,漲價

國慶期間,票價也要漲!

現在要在長途與火車中新增新的漲價通知。那麼在基類中新增介面: //

國慶漲價

public

abstract

void pricenationdayfloatup();

在兩個實現中新增實現:

public

override

void pricenationdayfloatup()

…… public

override

void pricenationdayfloatup()

(五)測試

busbus = new

bus();

bus.showprice();

bus.pricenationdayfloatup();

train

train = new

train();

train.showprice();

train.pricenationdayfloatup();

結果:長途汽車石家莊到邢台50元

國慶期間,汽車票在原價的基礎上,上浮5%!

火車石家莊到邢台40元

國慶期間,火車票在原價的基礎上,上浮3%!

如果將來國家生產力高度發達,票價下調,那麼,還要在兩個類實現的基礎上新增各自的通知方法。

現在以訪問者來實現整個通知系統

(一)訪問者抽象

漲價總是變,在不同的時期,總是要漲價。所以**因素這裡為訪問者。 //

上面的通知,漲價

public

abstract

class

notifyvisitor

(二)客運部門

長途汽車,火車部門接受訪問者的通知。 //

交通工具

public

abstract

class

vehicle

(三)客運部門實現

//bus

public

class

bus : vehicle

public

override

void accept(notifyvisitor visitor)

} //train

public

class

train : vehicle

public

override

void accept(notifyvisitor visitor)

} (四)春運要漲價

這是乙個實現的訪問者

public

class

newyearvisitor : notifyvisitor

public

override

void visit(train train)

} 它的目的就是通知兩個部門,要漲價及漲價的細節。

(五)交通管理部門

用於確定要漲價的部門。這是可分配的:交通工具有很多種,長途汽車與火車是其中的兩種,這次是兩者都要漲!

public

class

traffimnagement

public

void detach(vehicle vehicle)

public

void accept(notifyvisitor visitor)

} }

(六)測試

public

void testvisitor()

結果:長途汽車石家莊到邢台50元

春運開始了,汽車票在原價的基礎上,上浮20%!

火車石家莊到邢台40元

春運開始了,火車票在原價的基礎上,上浮15%!

(七)國慶期間漲價

新加國慶訪問者,其它的不用變動。

public

class

nationaldaynotifyvisitor : notifyvisitor

public

override

void visit(train train)

} (八)測試

public

void testvisitor()

結果:長途汽車石家莊到邢台50元

國慶節期間,汽車票在原價的基礎上,上浮5%!

火車石家莊到邢台40元

國慶節期間,火車票在原價的基礎上,上浮3%!

(九)生產力發達了,票價要降了! 新加

願望訪問者。

public

class

willvisitor : notifyvisitor

public

override

void visit(train train)

} (十)測試

public

void testvisitor()

結果:

長途汽車石家莊到邢台50元

生產力發達了人民幸福了,汽車票在原價的基礎上,下調90%!

火車石家莊到邢台40元

生產力發達了人民幸福了,火車票在原價的基礎上,下調90%!

visitor

模式通過所謂的雙重分發

(double dispatch)

來實現在不更改

element

類層次結構的前提下,在執行時透明的為類層次結構上的各個類動態新增新的操作。所謂雙重分發即

visitor

模式中間包括了兩個多型分發:第乙個為

accept

方法的多型辨析;第二個為

visit

方法的多型辨析(過載)

visitor

模式最大缺點在於擴充套件類層次結構(新增新的

element

子類),會導致

visitor

類的改變,因此

visitor

模式使使用者

element

類層子結構穩定,而其中的操作卻經常面臨頻繁改動。

當我們需要增加乙個交通工具的子類時,我們需要給

notifyvisitor

類新增乙個

visit

函式,並且

notifyvisitor

的每個派生類也必須新增。

java之訪問者模式

封裝某些作用於某種資料結構中各元素的操作,它可以在不改變資料結構的前提下定義作用於這些元素的新的操作。抽象訪問者 visitor 角色 宣告了乙個或者多個方法操作,形成所有的具體訪問者角色必須實現的介面。具體訪問者 concretevisitor 角色 實現抽象訪問者所宣告的介面,也就是抽象訪問者所...

設計模式之訪問者模式

先看一下下面這段 class person public string getaction public void setaction string action public void getconclusion else if action exciting else if action gri...

設計模式之訪問者模式

我們去銀行櫃檯辦業務,一般情況下會開幾個個人業務櫃檯的,你去其中任何乙個櫃檯辦理都是可以的。我們的訪問者模式可以很好付諸在這個場景中 對於銀行櫃檯來說,他們是不用變化的,就是說今天和明天提供個人業務的櫃檯是不需要有變化的。而我們作為訪問者,今天來銀行可能是取消費流水,明天來銀行可能是去辦理手機銀行業...