1、定義
訪問者模式(Vistor),表示一個作用於某對象結構中的各個元素的操作,它使你可以在不改變各個元素的類的前提下定義作用於這些元素的新操作。
2、UML
類解析:
Vistor:為每個對象結構中ConcreteElememt的每個類聲明一個Visit操作
ConcreteVistor1、ConcreteVistor2:具體訪問者,實現每個由Visitor聲明的操作,每個操作實現算法的一部分,而該算法片段乃是以允許訪問者訪問為元素。
ObjectStructure:能枚舉它的元素,可以提供一個高層的接口以允許訪問者訪問它的元素。
Element:定義一個Accept操作,它以一個訪問者為參數
ConcreteElement1、ConcreteElement2:具體元素,實現Accept操作
3、使用前提
訪問者模式使用與數據結構相對穩定的系統,它把數據結構和作用於結構上的操作之間的耦合解脫開,是的操作集合可以相對自由地演化。即上面ConcreteElement1、ConcreteElement2要相對穩定,如人只分“男人”和“女人”,如果經常變化就不適合用訪問者模式。
4、目的
目的是要你把處理從數據結構分離出來。
5、優點
增加新的操作很容易(即上面的ConcreteVistor1、ConcreteVistor2,添加一個很容易),因為增加新的操作就意味著增加一個新的訪問者,訪問者模式將有關的行為集中到一個訪問者對象中。
6、不足
增加新的數據結構變得困難。
7、名詞解釋
雙分派:雙分派意味著得到執行的操作決定於請求的種類和兩個接受者的類型。‘接受’方法就是一個雙分配的操作,它得到執行的操作不僅決定於Vistor類的具體實例,還決定於Element的具體實例。如:下面的例子,首先客戶端中將具體的vistor實例(ConcreteVistor1、或者ConcreteVistor2)傳遞給element類完成一次分配,然後element類調用具有參數的Vistor中的方法vistor.VistConcreteElementB(this),同時將自己(this)作為參數傳遞過去。
8、小試牛刀
package com.zcr.vistor;
public abstract class Element
{
public abstract void Accept(Vistor vistor);
}
package com.zcr.vistor;
public class ConcreteElementA extends Element
{
//充分利用雙分派技術,實現處理與數據結構的分離
@Override
public void Accept(Vistor vistor)
{
vistor.VistConcreteElementA(this);
}
public void OperationA()
{
}
}
package com.zcr.vistor;
public class ConcreteElementB extends Element
{
@Override
public void Accept(Vistor vistor)
{
vistor.VistConcreteElementB(this);
}
public void OperationB()
{
}
}
package com.zcr.vistor;
public abstract class Vistor
{
public abstract void VistConcreteElementA(ConcreteElementA concreteElementA);
public abstract void VistConcreteElementB(ConcreteElementB concreteElementB);
}
package com.zcr.vistor;
public class ConcreteVistor1 extends Vistor
{
@Override
public void VistConcreteElementA(ConcreteElementA concreteElementA)
{
System.out.println(concreteElementA.getClass().getName()+"被"+this.getClass().getName()+"訪問");
}
@Override
public void VistConcreteElementB(ConcreteElementB concreteElementB)
{
System.out.println(concreteElementB.getClass().getName()+"被"+this.getClass().getName()+"訪問");
}
}
package com.zcr.vistor;
public class ConcreteVistor2 extends Vistor
{
@Override
public void VistConcreteElementA(ConcreteElementA concreteElementA)
{
System.out.println(concreteElementA.getClass().getName()+"被"+this.getClass().getName()+"訪問");
}
@Override
public void VistConcreteElementB(ConcreteElementB concreteElementB)
{
System.out.println(concreteElementB.getClass().getName()+"被"+this.getClass().getName()+"訪問");
}
}
package com.zcr.vistor;
import java.util.ArrayList;
import java.util.List;
public class ObjectStructure
{
private List<Element> elements = new ArrayList<Element>();
public void Attach(Element element)
{
elements.add(element);
}
public void Detach(Element element)
{
elements.remove(element);
}
public void Accept(Vistor vistor)
{
for(Element e : elements)
{
e.Accept(vistor);
}
}
}
package com.zcr.vistor;
public class VistorTest
{
public static void main(String[] args)
{
ObjectStructure o = new ObjectStructure();
o.Attach(new ConcreteElementA());
o.Attach(new ConcreteElementB());
ConcreteVistor1 v1= new ConcreteVistor1();
ConcreteVistor2 v2= new ConcreteVistor2();
o.Accept(v1);
o.Accept(v2);
}
}