訪問者模式

2021-04-09 07:34:33 字數 4722 閱讀 5149

訪問者模式(visitor pattern)

訪問者模式是物件的行為模式。訪問者模式的目的是封裝一些施加於某種資料結構元素之上的操作。一旦這些操作需要修改的話,接受這個操作的資料結構則可以保持不變。

一、問題

集合是大多數的系統都要處理的一種容器物件,它儲存了對其它物件的引用。一般情況下,在集合上採取的操作都是針對同型別物件的同類操作,而迭代子模式就是為這種情況準備的設計模式。

但是,任何針對乙個儲存有不同型別物件的集合採取某種操作呢?

如果需要針對乙個包含不同型別元素的集合採取某種操作,而操作的細節根據元素的型別不同而有所不同時,就會出現必須對元素型別做型別判斷的條件轉移語句。而這些條件判斷語句會寫的很長,不利於**的維護。這個時候,使用訪問者模式是乙個值得考慮的方案。

二、訪問者模式

訪問者模式適用於資料結構相對未定的系統,它把資料結構和作用於結構之上的操作之間的耦合解脫開,使得操作集合可以相對自由的演化。

資料結構的每乙個節點都可以接受乙個訪問者的呼叫,此節點向訪問者物件傳入節點物件,二訪問者物件則反過來執行節點物件的操作。這樣的過程叫做「雙重分派」。節點呼叫訪問者,將它自己傳入,訪問者則將某演算法針對此節點執行。

雙重分派意味著施加於節點之上的操作是基於訪問者和節點本身的資料型別,而不僅是其中的一者。

三、訪問者模式的結構 1

、訪問者模式涉及的角色

(1)

抽象訪問者角色(visitor)

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

(2)

具體訪問者角色(concretevisitor)

:實現抽象訪問者所宣告的介面,也就是抽象訪問者所宣告的各個訪問操作。

(3)

抽象節點角色(node):

宣告乙個接受操作,接受乙個訪問者物件作為乙個參量。

(4)

具體節點角色(node):

實現了抽象元素所規定的接受操作。

(5)

結構物件角色(objectstructure)

:可以遍歷結構中所有的元素;如果需要,提供乙個高層次的介面讓訪問者物件可以訪問每乙個元素;如果需要,可以設計成乙個復合物件或乙個集合,如(list)或(set)。 2

、示意性源**

(1)

抽象訪問者角色

:為每個節點都提供了乙個訪問操作,接收相應的節點物件作為參量。

public inte***ce visitor

(2) 具體訪問者角色:

public class visitora implements visitor

public void visit(nodeb nodeb)

}

public class visitorb implements visitor

public void visit(nodeb nodeb)

}

(3) 抽象節點角色

:宣告了乙個接受操作

abstract public class node

(4) 具體節點角色

:接受乙個訪問者物件作為參量,同時還有若干個商業方法

public class nodea extends node

public string operationa()

}

public class nodeb extends node

public string operationb()

}

(5) 結構物件角色

:持有乙個集合,並向外界提供add()方法作為對集合的管理操作。通過呼叫這個方法,可以動態的增加乙個新的節點。

public class objectstructure

//執行訪問操作

public void action(visitor visitor)

}

//增加乙個新元素

public void add(node node)

}

(6) 客戶端

public class client

}

在實際系統中訪問者模式通常用來處理複雜的物件樹結構,而且訪問者模式可以用來處理跨越多個等級結構的樹結構問題。這正是訪問者模式的功能強大之處。 3

、系統的時序

(1)

準備過程

首先,客戶端建立了乙個結構物件,然後乙個新的節點物件a和b傳入。

其次,客戶端建立了乙個訪問者物件,並將此物件傳給結構物件。

然後,客戶端呼叫結構物件集合管理方法,將節點a和b加入到結構物件中。

最後,客戶端呼叫結構物件的行動方法,啟動訪問過程。

(2)

訪問過程

結構物件會遍歷它自己所儲存的集合中的所以節點。在本系統中就是節點a和b,首先a會被訪問到,這個訪問由以下操作組成 1

)節點a物件的接受方法被呼叫,並將訪問者a物件本身傳入; 2

)節點a反過來呼叫訪問者a物件的訪問方法,並將節點a物件本身傳入; 3

)訪問者a物件呼叫節點a物件的商業方法operaitona()。

從而完成了雙重分派過程,接著節點b物件被訪問,訪問過程和節點a的過程一樣。

因此,結構物件對集合元素的遍歷過程就是對集合中所有的節點進行委派的過程,也就是雙重分派過程,系統由多少個節點就會發生多少個雙重分派。

四、在什麼情況下應當使用訪問模式

在很多情況下不使用設計模式反而會得到乙個比較好的設計。每乙個設計模式都有其不應當使用的地方。訪問者模式也有不應當使用的情況。 1

、傾斜的擴充套件性

訪問者模式僅當在被訪問的類結構非常穩定的情況下使用。換言之,系統很少出現需要加入新節點的情況。如果出現需要加入新節點的情況怎麼辦呢?那時就必須在每個訪問物件裡加入乙個對應於這個新節點的訪問操作,而這是對系統的大規模修改,因而是違背「開-閉」原則的。

訪問者模式允許在節點中加入新的方法,相應的僅僅需要在乙個新的訪問者類加入此方法,而不需要在每乙個訪問者類中都加入此方法。

顯然,訪問者模式提供了傾斜的可擴充套件設計:方法集合的可擴充套件性和類集合的不可擴充套件性。

換言之,如果系統的資料結構是頻繁變化的,則不適合使用訪問者模式。 2

、「開—閉」原則和對變化的封裝

物件導向的設計原則只最重要的便是所謂的「開—閉」原則。乙個軟體系統的設計應當盡量做到對擴充套件開放,對修改關閉。達到這個原則的途徑就是遵循「對變化的封裝」的原則。即在進行軟體系統的設計時,應當設法找出乙個軟體系統中會變化的部分,將之封裝起來。

很多的系統可以按照演算法和資料結構分開,也就是說一些物件含有演算法,而另一些物件含有資料,接受演算法的操作。如果這樣的系統有比較穩定的資料結構,又有易於變化的演算法的話,使用訪問者沒收就是比較合適的。因為訪問者沒收使得演算法操作的增加變得容易。

反過來,如果乙個系統的資料結構物件易於變化,經常要有新的資料物件增加進來的話,就不適合使用訪問者沒收。因為在訪問者沒收中增加新的節點很困難,要涉及到在抽象訪問者和所有的具體訪問者中增加新的方法。

五、訪問者模式的優缺點 1

、優點

(1) 訪問者模式使得增加新的操作變得很容易。如果一些操作依賴於乙個複雜得結構物件的話,那麼一般而言,增加新的操作會很複雜。而使用訪問者模式,增加新的操作就意味著增加乙個新的訪問者類,因此,變的很容易。

(2)

訪問者模式將有關的行為集中到乙個訪問者物件中,而不是分散到乙個個節點類中。

(3)

訪問者模式可以跨越幾個類得等級結構訪問屬於不同的等級結構的成員類。迭代子只能訪問屬於同乙個型別等級結構的成員物件,而不能訪問屬於不同等級結構的物件。訪問者模式可以做到這一點。 2

、缺點

(1) 增加新的節點變的很困難。每增加乙個新的節點都意味著要在抽象訪問者角色中增加乙個新的抽象操作,並在每乙個具體訪問者類中增加相應的具體操作。

(2)

破壞封裝。訪問者模式要求訪問者物件訪問者並呼叫每乙個節點物件的操作,這隱含了乙個對所有節點物件的要求:它們必須暴露一些自己的操作和內部狀態。不然,訪問者的訪問者就變得沒有意義。由於訪問者物件自己會積累訪問者操作所需的狀態,從而使這些狀態不再儲存在節點物件中,這也是破壞封裝的。

六、訪問者模式的實現

當實現訪問者模式時,要將盡可能多的物件瀏覽邏輯放在visitor類中。而不是放在它的子類中。這樣的話,concretevisitor類所訪問的物件結構依賴較少,從而使維護較為容易。 1

、對節點結構的優化

訪問者模式所涉及的接受訪問的結構物件可以屬於乙個等級結構,也可以屬於不同的等級結構。對於每乙個等級結構而言,都可以通過將行為向上移動,將狀態向下移動而加以優化。**的優化方向與狀態的優化方向恰好相反。 2

、誰負責遍歷行為

由於每乙個訪問者都需要遍歷結構物件只的每乙個元素,因此,乙個自然的問題就是,哪乙個角色負責遍歷行為?可供選擇的有:結構物件、訪問者物件或者建立乙個新的迭代物件。

(1)

由結構物件負責迭代是最常見的選擇,這也是需要結構角色的出發點。

(2)

另乙個解決方案是使用乙個迭代物件來負責遍歷行為。

(3)

將遍歷行為放到訪問者中是第三個可能的選擇。一般而言,這樣做會導致每乙個具體訪問者都不得不具有管理集合的內部功能,而這在一般情況下是不理想的。然如果遍歷的邏輯較為複雜的話,將所有的遍歷邏輯放到結構角色中,不如將邏輯放到各個具體訪問者角色中。 3

、是否需要結構物件角色

如果遍歷行為是放到具體訪問者中,那麼結構物件角色就可以省略。 4

、是否需要抽象訪問者角色

抽象訪問者角色的設定是為了將可以復用的部分放在抽象類中,以便具體訪問者角色可以繼承,從而達到復用的目的。如果設計師非常肯定訪問者只有乙個,那麼設定抽象訪問者角色便沒有太大的意義,可以省略。

訪問者模式

行為模式中的訪問者模式 訪問者模式是物件的行為模式。訪問者模式的目的是封裝一些施加於某種資料結構元素之上的操作,一旦這些操作需要修改的話,接受這個操作的資料結構則可以保持不變。動機 類層次結構中可能經常由於引入新的操作,從而將型別變得脆弱。在軟體構建過程中,由於需求的改變,某些類層次結構中常常需要增...

訪問者模式

1.說明 namespace visitorspattern 象棋類 public abstract class chess public class redchess chess public class blackchess chess 在贏的情況下的狀態 public class win ac...

訪問者模式

1.意圖 資料結構和對資料結構操作的解耦。特點 資料結構是穩定的,操作是變化的。2 角色 1 抽象訪問者 宣告對所有元素訪問的介面 2 具體訪問者 3 抽象節點 宣告接收訪問者 抽象 為引數的 4 具體節點 5 物件結構 乙個例項的字段,或者使用聚集實現。注意的問題,適用性 1 存在乙個結構 節點的...