Visitor模式,在不修改已有程序結(jié)構(gòu)的前提下,通過添加額外的“訪問者”來完成對已有代碼功能的提升。
Visitor模式包括以下幾個(gè)元素:
1) 訪問者接口(Visitor):聲明一個(gè)訪問接口,定義visit接口,有幾個(gè)元素就定義幾個(gè)接口方法。接口方法的參數(shù)標(biāo)識了具體訪問元素角色,也就是說參數(shù)是一個(gè)具體類。這個(gè)地方也是Visitor的不足,
2) 具體訪問者(Concrete Visitor):實(shí)現(xiàn)Visitor接口
3) 元素接口(Element):定義一個(gè)accept方法,它以訪問者接口為參數(shù),這里不是具體的訪問者,即不知道具體的訪問者。
4) 具體元素(Concrete Element):實(shí)現(xiàn)元素(Element)接口中accept方法,控制訪問的流程。
5) 對象結(jié)構(gòu)(Object Structure):這是使用Visitor模式必須的角色。它要具備以下特征:能枚舉它的元素;可以提供一個(gè)高層的接口允許訪問者訪問它的元素;可以是一個(gè)集合,如一個(gè)列表或一個(gè)無序集合。
類圖如下:

具體代碼:
總結(jié):
1、元素接口和元素類都是依賴Visitor接口,而不是具體實(shí)現(xiàn)類,很好的實(shí)現(xiàn)了解耦。如果有一個(gè)新的元素歡迎Visitor參觀,只需要實(shí)現(xiàn)Visitable接口,并實(shí)現(xiàn)accept方法即可,都不牽涉具體的Visitor。
2、Visitor接口則不然,它依賴具體的元素,也就是說如果元素的類型發(fā)生變化如增加一個(gè)元素類型,那么Visitor接口和具體實(shí)現(xiàn)類都必須大改,這個(gè)是Visitor模式嚴(yán)重的缺陷。
3、Visitor模式名副其實(shí),好比旅行社、游客和景點(diǎn)的關(guān)系。旅行社就是Visitor接口,這次路線都需要參觀哪些景點(diǎn)通常是固定的(接口固定,如果要改變行程,通常很麻煩);游客就這些景點(diǎn),旅行社給你安排兩個(gè)小時(shí),你想自己怎么玩都行;景點(diǎn)則以不變應(yīng)萬變。這個(gè)比如也許有些不恰當(dāng),不過有助于理解這個(gè)模式。
Visitor模式包括以下幾個(gè)元素:
1) 訪問者接口(Visitor):聲明一個(gè)訪問接口,定義visit接口,有幾個(gè)元素就定義幾個(gè)接口方法。接口方法的參數(shù)標(biāo)識了具體訪問元素角色,也就是說參數(shù)是一個(gè)具體類。這個(gè)地方也是Visitor的不足,
2) 具體訪問者(Concrete Visitor):實(shí)現(xiàn)Visitor接口
3) 元素接口(Element):定義一個(gè)accept方法,它以訪問者接口為參數(shù),這里不是具體的訪問者,即不知道具體的訪問者。
4) 具體元素(Concrete Element):實(shí)現(xiàn)元素(Element)接口中accept方法,控制訪問的流程。
5) 對象結(jié)構(gòu)(Object Structure):這是使用Visitor模式必須的角色。它要具備以下特征:能枚舉它的元素;可以提供一個(gè)高層的接口允許訪問者訪問它的元素;可以是一個(gè)集合,如一個(gè)列表或一個(gè)無序集合。
類圖如下:

具體代碼:
public interface Visitor
{
public void visitCollection(Collection collection);
public void visitString(String string);
public void visitFloat(Float float);
}
{
public void visitCollection(Collection collection);
public void visitString(String string);
public void visitFloat(Float float);
}
public class ConcreteVisitor1 implements Visitor
{
//在本方法中,我們實(shí)現(xiàn)了對Collection的元素的成功訪問
public void visitCollection(Collection collection) {
Iterator iterator = collection.iterator()
while (iterator.hasNext()) {
Object o = iterator.next();
if (o instanceof Visitable)
((Visitable)o).accept(this);
}
public void visitString(String string) {
System.out.println("'"+string+"'");
}
public void visitFloat(Float float) {
System.out.println(float.toString()+"f");
}
}
{
//在本方法中,我們實(shí)現(xiàn)了對Collection的元素的成功訪問
public void visitCollection(Collection collection) {
Iterator iterator = collection.iterator()
while (iterator.hasNext()) {
Object o = iterator.next();
if (o instanceof Visitable)
((Visitable)o).accept(this);
}
public void visitString(String string) {
System.out.println("'"+string+"'");
}
public void visitFloat(Float float) {
System.out.println(float.toString()+"f");
}
}
public interface Visitable
{
public void accept(Visitor visitor);
}
public class StringElement implements Visitable
{
private String value;
public ConcreteElement(String string) {
value = string;
}
//定義accept的具體內(nèi)容 這里是很簡單的一句調(diào)用
public void accept(Visitor visitor) {
visitor.visitString(this);
}
}
public class FloatElement implements Visitable
{
private Float value;
public ConcreteElement(Float f) {
value = f;
}
//定義accept的具體內(nèi)容 這里是很簡單的一句調(diào)用
public void accept(Visitor visitor) {
visitor.visitFloat(this);
}
}
{
public void accept(Visitor visitor);
}
public class StringElement implements Visitable
{
private String value;
public ConcreteElement(String string) {
value = string;
}
//定義accept的具體內(nèi)容 這里是很簡單的一句調(diào)用
public void accept(Visitor visitor) {
visitor.visitString(this);
}
}
public class FloatElement implements Visitable
{
private Float value;
public ConcreteElement(Float f) {
value = f;
}
//定義accept的具體內(nèi)容 這里是很簡單的一句調(diào)用
public void accept(Visitor visitor) {
visitor.visitFloat(this);
}
}
總結(jié):
1、元素接口和元素類都是依賴Visitor接口,而不是具體實(shí)現(xiàn)類,很好的實(shí)現(xiàn)了解耦。如果有一個(gè)新的元素歡迎Visitor參觀,只需要實(shí)現(xiàn)Visitable接口,并實(shí)現(xiàn)accept方法即可,都不牽涉具體的Visitor。
2、Visitor接口則不然,它依賴具體的元素,也就是說如果元素的類型發(fā)生變化如增加一個(gè)元素類型,那么Visitor接口和具體實(shí)現(xiàn)類都必須大改,這個(gè)是Visitor模式嚴(yán)重的缺陷。
3、Visitor模式名副其實(shí),好比旅行社、游客和景點(diǎn)的關(guān)系。旅行社就是Visitor接口,這次路線都需要參觀哪些景點(diǎn)通常是固定的(接口固定,如果要改變行程,通常很麻煩);游客就這些景點(diǎn),旅行社給你安排兩個(gè)小時(shí),你想自己怎么玩都行;景點(diǎn)則以不變應(yīng)萬變。這個(gè)比如也許有些不恰當(dāng),不過有助于理解這個(gè)模式。