Visitor访问者模式
访问者模式表示一个作用于某对象结构中的各元素的操作,它使你可以在不改变各元素类的前提下定义作用于这些元素的新操作。 从定义可以看出结构对象是使用访问者模式的必备条件,而且这个结构对象必须存在遍历自身各个对象的方法,类似于Java中的Collection。
访问者模式的目的是要把处理从数据结构中分离出来,如果系统有比较稳定的数据结构,又有易于变化的算法的话,使用访问者模式是个不错的选择,因为访问者模式使的算法操作的增加变得容易。相反,如果系统的数据结构不稳定,易于变化,则此系统就不适合使用访问者模式了。
访问者模式结构
访问者角色(Visitor):
为该对象结构中具体元素角色声明一个访问操作接口.
具体访问者角色(Concrete Visitor):
实现每个由访问者角色(Visitor)声明的操作.
元素角色(Element):
定义一个Accept操作,它以一个访问者为参数.
具体元素角色(Concrete Element):
实现由元素角色提供的Accept操作.
对象结构角色(Object Structure):
这是使用访问者模式必备的角色. 它要具备以下特征: 能枚举它的元素; 可以提供一个高层的接口以允许该访问者访问它的元素; 可以是一个复合(组合模式)或是一个集合, 如一个列表或一个无序集合.
访问者模式的优点
● 好的扩展性
能够在不修改对象结构中的元素的情况下,为对象结构中的元素添加新的功能。
● 好的复用性
可以通过访问者来定义整个对象结构通用的功能,从而提高复用程度。
● 分离无关行为
可以通过访问者来分离无关的行为,把相关的行为封装在一起,构成一个访问者,这样每一个访问者的功能都比较单一。
访问者模式的缺点
● 对象结构变化很困难
不适用于对象结构中的类经常变化的情况,因为对象结构发生了改变,访问者的接口和访问者的实现都要发生相应的改变,代价太高。
● 破坏封装
访问者模式通常需要对象结构开放内部数据给访问者和ObjectStructrue,这破坏了对象的封装性。
DEMO
public interface Visitor
{
public void visit(GladiolusConcreteElement gladiolus);
public void visit(ChrysanthemumConreteElement chrysanthemum);
}
public interface FlowerElement
{
public void accept(Visitor visitor);
}
public class GladiolusConcreteElement implements FlowerElement
{
@Override
public void accept(final Visitor visitor)
{
visitor.visit(this);
}
}
public class ChrysanthemumConreteElement implements FlowerElement
{
@Override
public void accept(final Visitor visitor)
{
visitor.visit(this);
}
}
public class GladiolusVisitor implements Visitor
{
@Override
public void visit(final GladiolusConcreteElement gladiolus)
{
System.out.println(this.getClass().getSimpleName() + " access " + gladiolus.getClass().getSimpleName());
}
@Override
public void visit(final ChrysanthemumConreteElement chrysanthemum)
{
System.out.println(this.getClass().getSimpleName() + " access " + chrysanthemum.getClass().getSimpleName());
}
}
public class ChrysanthemumConreteElement implements FlowerElement
{
@Override
public void accept(final Visitor visitor)
{
visitor.visit(this);
}
}
public class ObjectStructure
{
private final List<FlowerElement> elements = new ArrayList<FlowerElement>();
public void addElement(final FlowerElement e)
{
elements.add(e);
}
public void removeElement(final FlowerElement e)
{
elements.remove(e);
}
public void accept(final Visitor visitor)
{
for (final FlowerElement e : elements)
{
e.accept(visitor);
}
}
}
public class Client
{
public static void main(final String[] args)
{
final ObjectStructure os = new ObjectStructure();
os.addElement(new GladiolusConcreteElement());
os.addElement(new ChrysanthemumConreteElement());
final GladiolusVisitor gVisitor = new GladiolusVisitor();
final ChrysanthemumVisitor chVisitor = new ChrysanthemumVisitor();
os.accept(gVisitor);
os.accept(chVisitor);
}
}