Visitor模式,在不修改已有程序結構的前提下,通過添加額外的“訪問者”來完成對已有代碼功能的提升。
Visitor模式包括以下幾個元素:
1) 訪問者接口(Visitor):聲明一個訪問接口,定義visit接口,有幾個元素就定義幾個接口方法。接口方法的參數標識了具體訪問元素角色,也就是說參數是一個具體類。這個地方也是Visitor的不足,
2) 具體訪問者(Concrete Visitor):實現Visitor接口
3) 元素接口(Element):定義一個accept方法,它以訪問者接口為參數,這里不是具體的訪問者,即不知道具體的訪問者。
4) 具體元素(Concrete Element):實現元素(Element)接口中accept方法,控制訪問的流程。
5) 對象結構(Object Structure):這是使用Visitor模式必須的角色。它要具備以下特征:能枚舉它的元素;可以提供一個高層的接口允許訪問者訪問它的元素;可以是一個集合,如一個列表或一個無序集合。
類圖如下:
具體代碼:
public interface Visitor
{
public void visitCollection(Collection collection);
public void visitString(String string);
public void visitFloat(Float float);
}
public class ConcreteVisitor1 implements Visitor
{
//在本方法中,我們實現了對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的具體內容 這里是很簡單的一句調用
public void accept(Visitor visitor) {
visitor.visitString(this);
}
}
public class FloatElement implements Visitable
{
private Float value;
public ConcreteElement(Float f) {
value = f;
}
//定義accept的具體內容 這里是很簡單的一句調用
public void accept(Visitor visitor) {
visitor.visitFloat(this);
}
}
總結:
1、元素接口和元素類都是依賴Visitor接口,而不是具體實現類,很好的實現了解耦。如果有一個新的元素歡迎Visitor參觀,只需要實現Visitable接口,并實現accept方法即可,都不牽涉具體的Visitor。
2、Visitor接口則不然,它依賴具體的元素,也就是說如果元素的類型發生變化如增加一個元素類型,那么Visitor接口和具體實現類都必須大改,這個是Visitor模式嚴重的缺陷。
3、Visitor模式名副其實,好比旅行社、游客和景點的關系。旅行社就是Visitor接口,這次路線都需要參觀哪些景點通常是固定的(接口固定,如果要改變行程,通常很麻煩);游客就這些景點,旅行社給你安排兩個小時,你想自己怎么玩都行;景點則以不變應萬變。這個比如也許有些不恰當,不過有助于理解這個模式。