X.d 笔记

小Web,大世界

0%

设计模式(23):访问者模式 Visitor

访问者模式有一点点类似代理,一个对象可以访问另外一个对象,但比代理智能很多

访问者模式 Visitor

访问者模式的目的是封装一些施加于某种数据结构元素之上的操作。一旦这些操作需要修改的话,接受这个操作的数据结构可以保持不变。访问者模式适用于数据结构相对未定的系统,它把数据结构和作用于结构上的操作之间的耦合解脱开,使得操作集合可以相对自由的演化。

访问者模式使得增加新的操作变的很容易,就是增加一个新的访问者类。访问者模式将有关的行为集中到一个访问者对象中,而不是分散到一个个的节点类中。当使用访问者模式时,要将尽可能多的对象浏览逻辑放在访问者类中,而不是放到它的子类中。访问者模式可以跨过几个类的等级结构访问属于不同的等级结构的成员类。

问题:

Many distinct and unrelated operations need to be performed on node objects in a heterogeneous aggregate structure. You want to avoid “polluting” the node classes with these operations. And, you don’t want to have to query the type of each node and cast the pointer to the correct type before performing the desired operation.

意图:

  • Represent an operation to be performed on the elements of an object structure. Visitor lets you define a new operation without changing the classes of the elements on which it operates.
  • The classic technique for recovering lost type information.
  • Do the right thing based on the type of two objects.
  • Double dispatch

代码

例:比如你电话打车,打个电话给接接线员说你要打车,留了位置,然后接线员就打电话给司机说明情况,司机同义接客后,接线员通知你将有司机来接,这里的接线员就相当于访问者,即可以访问你,也可以访问司机

代码1:访问者Visitor与被访问者Person

public interface Visitor {
    //访问司机
    public void visit(Driver driver);
    //访问乘客
    public void visit(Passenger passenger);

}
public abstract class Person {
    public abstract boolean accept(Visitor v);
}

代码2:访问者的实例之一:热线电话

/**
 * 实例化的访问者,本例可以是热线电话,也可以是,号码百事通,中介,打车软件什么什么的
 * */
public class HotLine implements Visitor{

    @Override
    public void visit(Driver driver) {
        System.out.println("热线电话:工作人员正在访问 下一个司机");
        if(driver.accept(this)){
            System.out.println("热线电话:已经有司机愿意为您服务");
        }else{
            this.visit(new Driver());
        }
    }

    @Override
    public void visit(Passenger passenger) {
        if(passenger.accept(this)){
            this.visit(new Driver());
        }
    }

}

代码3:被访问者的实例乘客与司机

public class Passenger extends Person{
    /**
     * 这个例子比较撮,应该是乘客访问热线电话才对,接受访问
     * */
    @Override
    public boolean accept(Visitor v) {
        System.out.println("乘客:我要搭个车");
        return true;
    }

}
public class Driver extends Person{

    private static int index=0;

    //司机接受访问时的应答
    @Override
    public boolean accept(Visitor v) {
        index++;
        if(index%3==0){
            System.out.println("司机"+index+"号:可以载客");
            return true;
        }else{
            System.out.println("司机"+index+"号:不想载客");
            return false;
        }
    }

}

代码4:客户端调用

public static void main(String[] args){
    Passenger p  = new Passenger();
    Visitor v = new HotLine();
    v.visit(p);
}

小结

访问者模式 Visitor

  • 使用频率:
    此模式构造起来有点小不爽,使用时也需要明确很多东西,虽然功能强大但要多写很多行代码,没有特殊要求一般也较少使用。

  • 利弊影响:
    一般如果要新增访客或更多的属性也是件很麻烦的事