目录
访问者模式
访问者模式是一种较为复杂的行为型设计模式,它包含访问者和被访问元素两个主要组成部分,这些被访问的元素具有不同的类型,且不同的访问者可以对其施加不同的访问操作.访问者模式使得用户可以在不修改现有系统的情况下扩展系统的功能,为这些不同类型的元素增加新的操作.
访问者模式概述
访问者模式的动机就是以不同的方式操作复杂对象结构.
在使用访问者模式时,被访问元素通常不是单独存在的,它们存储在一个集合中,这个集合被称为"对象结构",访问者通过遍历对象结构实现对其中存储的元素的逐个操作.
访问者模式:表示一个作用于某对象结构中的各个元素的操作.访问者模式让用户可以在不改变各元素的类的前提下定义作用于这些元素的新操作.
访问者模式是一种对象行为型模式,它为操作存储不同类型元素的对象结构提供了一种解决方案,用户可以对不同类型的元素施加不同的操作.
访问者模式结构
访问者模式包含5个角色:
- 抽象访问者
- 具体访问者
- 抽象元素
- 具体元素
- 对象结构
访问者模式实现
抽象访问者
abstract class Visitor {
//使用重载的方式来定义多个方法,用于操作不同类型的元素对象.
public abstract void visit(ConcreteElementA elementA);
public abstract void visit(ConcreteElementB elementB);
public void visit(ConcreteElementC elementC){
//元素ConcreteElementC操作代码
}
}
具体访问者
class ConcreteVisitor extends Visitor {
public void visit(ConcreteElementA elementA){
//元素ConcreteElementA操作代码
}
public void visit(ConcreteElementB elementB){
//元素ConcreteElementB操作代码
}
}
抽象元素类
interface Element {
public void accept(Visitor visitor);
}
具体元素类
class ConcreteElementA implements Element {
public void accept(Visitor visitor){
visitor.visit(this);
}
public void operationA(){
//业务方法
}
}
在具体元素类ConcreteElementA的accept()方法中,通过调用Visitor类的visit()方法实现对元素的访问,并以当前对象作为visit()方法的参数.其具体执行过程如下:
- 调用具体元素类的accept(Visitor visitor)方法,并将Visitor子类对象作为其参数.
- 在具体元素类accept(Visitor visitor)方法内部调用传入的Visitor对象的visit()方法,如visit(ConcreteElementA elementA),将当前具体元素类对象(this)作为参数,如visitor.visit(this).
- 执行Visitor对象的visit()方法,在其中还可以调用具体元素对象的业务方法,
这种调用机制也称为“双重分派”,正因为使用了双重分派机制,使得增加新的访问者无须修改现有类库代码,只需将新的访问者对象作为参数传入具体元素对象的accept()方法,程序运行时将回调在新增Visitor类中定义的visit()方法,从而增加新的元素访问方式.
对象结构
class ObjectStructure {
private ArrayList<Element> list = new ArrayList<Element>(); //定义一个集合用于存储元素对象
public void accept(Visitor visitor){
Iterator i=list.iterator();
while(i.hasNext())
{
((Element)i.next()).accept(visitor); //遍历访问集合中的每一个元素
}
}
public void addElement(Element element){
list.add(element);
}
public void removeElement(Element element){
list.remove(element);
}
}
在对象结构中可以使用迭代器对存储在集合中的元素对象进行遍历,并逐个调用每一个对象的accept()方法,实现对元素对象的访问操作.
访问者模式与组合模式联用
在访问者模式中包含一个用于存储元素对象集合的对象结构,通常可以使用迭代器来遍历对象结构,同时具体元素之间可以存在整体和部分关系,有些元素作为容器对象,有些元素作为成员对象,可以使用组合模式来组织元素.
访问者模式优/缺点与适用环境
由于访问者模式的使用条件较为苛刻,本身结构也较为复杂,因此在实际应用中使用频率不是特别高.当系统中存在一个较为复杂的对象结构,且不同访问者对其所采取的操作也不相同时,可以考虑使用访问者模式进行设计.在XML文档解析,编译器的设计,复杂集合对象的处理等领域访问者模式得到了一定的应用.
访问者模式优点
- 增加新的访问操作很方便.
- 将有关元素对象的访问行为集中到一个访问者对象中,而不是分散在一个个的元素类中,类的职责更加清晰.
- 让用户能够在不修改现有元素类层次结构的情况下定义作用于该层次结构的操作.
访问者模式缺点
- 增加新的元素类很困难,而且还可能破坏系统的封装性.
访问者模式适用场景
- 一个对象结构包含多个类型的对象,希望对这些对象实施一些依赖其具体类型的操作.
- 需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而需要避免让这些操作"污染"这些对象的类,也不希望在增加新操作是修改这些类.
- 对象结构中对象对应的类很少改变,但经常需要在此对象结构上定义新的操作.