访问者模式(Visitor)表示一个作用于某对象结构中的各元素的操作,它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。
适用于数据结构相对稳定的系统!
一、 涉及角色
抽象访问者(Visitor):声明了一个或多个访问操作,形成所有的具体元素角色必须实现的接口
具体访问者(ConcreteVisitor):实现抽象访问者角色所声明的接口,也就是抽象访问者所声明的各个访问操作。
抽象节点(Node)角色:声明一个接受(accept)操作,接受一个访问者为参数。
具体节点(ConcreteNode)角色:实现accept操作
结构对象(ObjectStructure)角色:可以遍历结构中的所有元素;提供一个高层次的接口让访问者对象可以访问每一个元素;可以设计一个复合对象或一个聚集,
二、 适用范围
1、 一个对象结构包含很多类对象,它们有不同的接口,而你想对这些对象实施一些依赖于其具体类的操作。
2、 需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而你想避免让这些操作“污染”这些对象的类。
Visitor使得你可以将相关的操作集中起来定义在一个类中。
当该对象结构被很多应用共享时,用Visitor模式让每个应用仅包含需要用到的操作。
3、 定义对象结构的类很少改变,但经常需要在此结构中定义新的操作。
改变对象结构类 需要重定义对所有访问者的接口,可能需要很大的代价。如果对象结构类经常改变,那么可能还是在这些类中定义这些操作较好
三、 优点与缺点
1)、容易增加新的操作,使用访问者模式,增加新的操作类似于增加一个新的访问者类。
2)、访问者模式将有关行为集中到一个访问者对象中,而不是分散到一个个节点类。
3)、可以跨过几个类的等级结构访问属于不同的等级结构的成员类。
缺点:
1)、增加新的节点类很困难。每增加一个新的节点意味着要在 抽象访问者角色中增加一个新的抽象操作,并在每个具体访问者类中增加相应的具体操作。
2)、破坏封装。访问者要求访问并调用每一个节点对象操作,使得节点对象必须暴露自己的操作和内部状态。
注意:当实现访问者模式时,要将尽可能多的对象浏览逻辑放在 Visitor类中,而不是放在它的子类里。这样的话,ConcreteVisitor类对所访问的对象结构依赖较少,从而使维护较为容易。
四、故事说明
23、VISITOR—情人节到了,要给每个MM送一束鲜花和一张卡片,可是每个MM送的花都要针对她个人的特点,每张卡片也要根据个人的特点来挑,我一个人哪搞得清楚,还是找花店老板和礼品店老板做一下Visitor,让花店老板根据MM的特点选一束花,让礼品店老板也根据每个人特点选一张卡,这样就轻松多了;
访问者模式:访问者模式的目的是封装一些施加于某种数据结构元素之上的操作。一旦这些操作需要修改的话,接受这个操作的数据结构可以保持不变。访问者模式适用于数据结构相对未定的系统,它把数据结构和作用于结构上的操作之间的耦合解脱开,使得操作集合可以相对自由的演化。访问者模式使得增加新的操作变的很容易,就是增加一个新的访问者类。访问者模式将有关的行为集中到一个访问者对象中,而不是分散到一个个的节点类中。当使用访问者模式时,要将尽可能多的对象浏览逻辑放在访问者类中,而不是放到它的子类中。访问者模式可以跨过几个类的等级结构访问属于不同的等级结构的成员类。
抽象访问者
public abstract class Visitor {
public abstract void visitString(StringNode stringNode);
public abstract void visitFloat(FloatNode stringNode);
}
具体访问者(ConcreteVisitor)
public class ConcreteVisitor extends Visitor{
@Override
public void visitString(StringNode stringNode) {
stringNode.toString();
}
@Override
public void visitFloat(FloatNode floatNode) {
floatNode.toString();
}
}
抽象节点(Node)
public interface Node {
public void accept(Visitor visitor);
}
具体节点(ConcreteNode)
public class FloatNode implements Node{
private float data;
public FloatNode(float data) {
this.data = data;
}
@Override
public void accept(Visitor visitor) {
visitor.visitFloat(this);
}
public String toString() {
System.out.println("格式浮点数:" + data + "----f");
return data + "";
}
}
具体节点(ConcreteNode)
public class StringNode implements Node{
private String data;
public StringNode(String data) {
this.data = data;
}
@Override
public void accept(Visitor visitor) {
visitor.visitString(this);
}
@Override
public String toString() {
System.out.println("格式字符串:" + data + "---s");
return data;
}
}
结构对象(ObjectStructure)
public class ObjectStructure {
private List<Node> nodeList = new ArrayList<Node>() ;
public void addNodes(Node node){
nodeList.add(node);
}
public void accept(Visitor visitor){
for (int i = 0; i < nodeList.size(); i++) {
nodeList.get(i).accept(visitor);
}
}
}
客户端
package visitor;
public class Client {
public static void main(String[] args) {
StringNode stringNode = new StringNode("hello!");
FloatNode floatNode = new FloatNode(2.1f);
ObjectStructure o = new ObjectStructure();
o.addNodes(floatNode);
o.addNodes(stringNode);
Visitor visitor = new ConcreteVisitor();
o.accept(visitor);
}
}
/*格式浮点数:2.1----f
格式字符串:hello!---s*/