设计模式之访问者模式——初学
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);
}
}