zoukankan      html  css  js  c++  java
  • 浅谈Visitor Pattern

          第一步:   在介绍Visitor Pattern (访问者模式)之前,先简要介绍一下:双重分派。

    在Visitor Pattern中双重分派是指:数据结构的每一个节点都可以接受一个访问者的调用(这句话的代码是:在具体的节点类中有形如如下的方法accept(Visitor visitor){visitor.visitor(this)},说白一点就是,在节点类中有一个方法,以访问者作为参数,这个访问者也就是Visitor接口),此节点向访问者对象传入节点对象,而访问者对象反过来执行节点对象的操作。(这句话的代码是:在具体的访问者类中,有形如一个visitor(ConcreteNode node){node.operation()}的方法,说白点就是在Visitor接口中有益具体节点为参数的方法,有几个具体节点,就有几个方法)这样的过程就叫做双重分派。

      第二步:介绍访问者模式所涉及的角色:

    访问者模式的角色有6个,分别是:Visitor(抽象访问者) 、ConcreteVisitor(具体访问者)、Node(抽象节点),ConcreteNode(具体节点)、ObjectStructure(结构对象,你也可以翻译为对象结构,其实我更喜欢对象结构。)Client(客户,相当于一个测试类)

      第三步:代码示例,把各个角色的代码抽象出来。

    Visitor(抽象访问者)是一个接口或者,抽象类,其代码如下:

    package com.qls.visitorPattern5;

    public interface Visitor {
    /**
    * NodeA,NodeB分别是Node接口的两个具体实现类,
    * 由于本例展示两个Node的具体实现类,所以Visitor接口中的抽象方法只有两个
    * 一般而言:有多少个具体节点的实现类,在Visitor接口中就有多少个抽象方法。
    * 这是因为:每一个具体的节点都有独一无二的业务方法(business method).
    * @param node
    */
    void visitor(NodeA node);
    void visitor(NodeB node);
    }

    ConcreteVisitor(具体访问者)是Visitor的实现类,其代码如下:

     第一个具体访问者的代码如下:

    package com.qls.visitorPattern5;

    public class VisitorA implements Visitor {

    @Override
    public void visitor(NodeA node) {
    // TODO Auto-generated method stub
    node.operation();//这个operation()是NodeA的特有的业务方法
    }

    @Override
    public void visitor(NodeB node) {
    // TODO Auto-generated method stub
    node.operation();//这个operation()是NodeB的特有的业务方法
    }

    }

     第二个具体访问者的代码如下:

    package com.qls.visitorPattern5;

    public class VisitorB implements Visitor {

    @Override
    public void visitor(NodeA node) {
    // TODO Auto-generated method stub
    node.operation();
    }

    @Override
    public void visitor(NodeB node) {
    // TODO Auto-generated method stub
    node.operation();
    }

    }

    Node(抽象节点)是一个接口,或者抽象类。是所有具体节点的基类.

    package com.qls.vistitorPattern3;
    /**
    * 在Node接口中有以Visitor(抽象访问者)为参数的方法
    * @author 秦林森
    *
    */
    public interface Node {
    void accept(Visitor visitor);
    }

    ConcreteNode(具体节点)本例中有两个具体节点。

    第一个具体节点的代码如下:

    package com.qls.vistitorPattern3;

    public class NodeA implements Node {

    @Override
    public void accept(Visitor visitor) {
    // TODO Auto-generated method stub
    /**
    * 这个this指代NodeA,其检验方法为:
    * System.out.println("this 所指代的类是:"+this.getClass());
    当我们不确定this,指代谁时,可以用这种方法进行检测。
    */
    visitor.visitor(this);

    }
    //NodeA 所特有的业务方法或者称为商业方法
    void operation(){
    System.out.println("this is nodeA's operation");
    }

    }

    第二个具体节点的代码如下:

    package com.qls.vistitorPattern3;

    public class NodeB implements Node {
    /**
    * 表示接受一个访问者。进行访问这个节点NodeB,执行NodeB所特有的业务方法。
    */
    @Override
    public void accept(Visitor visitor) {
    // TODO Auto-generated method stub
    visitor.visitor(this);
    }
    //NodeB 所特有的业务方法或者称为商业方法
    void operation(){
    System.out.println("this is nodeB's operation");
    }
    }

    ObjectStructure(结构对象),这个角色的作用,以我个人的理解就是建立Visitor和Node关系的一个类。

    其代码如下:

    package com.qls.visitorPattern5;

    import java.util.Enumeration;
    import java.util.Vector;

    public class ObjectStructure {
    /**
    * 一个容器用来存放Node,这个容器可以是ArrayList,Set等等不一定就非是Vector不可
    */
    private Vector<Node> nodes;
    private Node node;
    public ObjectStructure() {
    nodes=new Vector<Node>();
    }
    public void action(Visitor visitor){
    Enumeration<Node> e = nodes.elements();
    while(e.hasMoreElements()){
    node = e.nextElement();
    node.accept(visitor);//接受访问者,让访问者执行具体节点的相关操作。
    }
    }
    /**
    * 添加节点
    * @param args
    */
    public void add(Node node){
    nodes.addElement(node);
    }
    public static void main(String[] args) {
    // TODO Auto-generated method stub

    }

    }

    Client(客户)其作用就相当于一个测试类,把各个具体节点的业务方法的结果打印出来。

    其代码如下:

    package com.qls.visitorPattern5;

    public class Client {
    private static ObjectStructure objectStructure;
    // private static Visitor visitor;
    // private static Node node;
    public static void main(String[] args) {
    // TODO Auto-generated method stub
    objectStructure=new ObjectStructure();//这步必须写,后者会报NullPointException
    //添加一个节点
    objectStructure.add(new NodeA());
    objectStructure.add(new NodeB());
    //创建一个访问者
    objectStructure.action(new VisitorA());
    //创建一个访问者
    objectStructure.action(new VisitorB());
    }

    }

    上述代码的运行结果为:由于我让两个访问者去访问ObjectStructure,具体节点的操作,是由具体访问者代劳的,所以运行结果为:

    //前两句话是由objectStructure.action(new VisitorA());所产生的。

    //后两句话是由:objectStructure.action(new VisitorB());所产生的。

    this is nodeA's business method
    this is NodeB's business method
    this is nodeA's business method
    this is NodeB's business method

     

     

  • 相关阅读:
    最强JAVA核心技术群
    脚本加载整个文件夹的jar到环境变量
    TTS 中文转制 google
    vue+webpack+sass
    springboot入门程序
    vue+ui
    正则表达式
    vue全家桶router、vuex、axios
    vue基础
    springboot获取自定义配置的值、获取类型安全的自定义配置的值和profile配置
  • 原文地址:https://www.cnblogs.com/1540340840qls/p/6136766.html
Copyright © 2011-2022 走看看