Design Patterns of the Visitor Pattern (Visitor Pattern) Introducing the Visitor PatternVisitor Pattern ExamplesVisitor Pattern Analysis


  • Introduction of the visitor model
  • Example of the accessor pattern
  • Analysis of the accessor model

Introduction of the visitor model

Visitor means visitor. The data structure holds the elements. Generally we need to process the elements, so where do we put the code to process the elements? The most obvious way to do this is to put it in the class of the data structure and add methods to the class for processing. But with a lot of processing, it's more problematic, and every time a processing is added, we have to go and modify the class that represents the data structure. The visitor pattern is used to solve this problem. The visitor pattern separates the definition of data structures from their processing. That is, a new visitor class will be added, giving the processing of data elements to the visitor class, so that when new processing is to be added later, only the visitor will be added.

Example of the visitor pattern

We will combine the composite pattern in this example [http://www.jianshu.com/p/685dd6299d96] Adding and changing on top of the example in , the folder and file represent the data structure we want to access, and then we implement the visitor to output the contents of the folder and file.

Let's see first.Class diagram.

image.png

We see that for that part of the data structure there is an interface element, this interface is used to accept visitors to an interface, which has only one method is to accept a visitor, and then subclass the specific data structure to go back and implement this this method.

package Visitor;

public interface Element {
    public abstract void accept(Visitor v);
}

Then the visitor has an abstract class that can inherit this method added according to the different types of access handling, here the visitor can also be implemented with an interface the author believes.

package Visitor;

public abstract class Visitor {
    public abstract void visit(File file);
    public abstract void visit(Directory directory);
}

The accessor defines two abstract methods for accessing the file class and the directory class, respectively

Next, look at the specific visitor implementation.

package Visitor;

import java.util.Iterator;

public class ListVisitor extends Visitor {
    private String currentdir = "";                      
    public void visit(File file) {                  
        System.out.println(currentdir + "/" + file);
    }
    public void visit(Directory directory) {  
        System.out.println(currentdir + "/" + directory);
        String savedir = currentdir;
        currentdir = currentdir + "/" + directory.getName();
        Iterator it = directory.iterator();
        while (it.hasNext()) {
            Entry entry = (Entry)it.next();
            entry.accept(this);
        }
        currentdir = savedir;
    }
}

Here's the specific processing logic code.

The file and directory classes need to implement the element interface and implement the accpet method is to accept a visitor object and call the visitor object to access itself

package Visitor;

public class File extends Entry {
    private String name;
    private int size;
    public File(String name, int size) {
        this.name = name;
        this.size = size;
    }
    public String getName() {
        return name;
    }
    public int getSize() {
        return size;
    }
    public void accept(Visitor v) {
        v.visit(this);
    }
}
package Visitor;

import java.util.Iterator;
import java.util.ArrayList;

public class Directory extends Entry {
     private String name;                     // Documents
     private ArrayList dir = new ArrayList();       / / Speculum
     public Directory(String name) { // English (name)
        this.name = name;
    }
     public String getName() { // The latest version of the CRM service
        return name;
    }
     public int getSize() { // The size of the CRM
        int size = 0;
        Iterator it = dir.iterator();
        while (it.hasNext()) {
            Entry entry = (Entry)it.next();
            size += entry.getSize();
        }
        return size;
    }
     public Entry add(Entry entry) { // Speculum
        dir.add(entry);
        return this;
    }
     public Iterator iterator() { // Iterator
        return dir.iterator();
    }
     public void accept(Visitor v) { // License keyword
        v.visit(this);
    }
}
package Visitor;


import java.util.Iterator;

public abstract class Entry implements Element {
    public abstract String getName();                                 
    public abstract int getSize();                                      
    public Entry add(Entry entry) throws FileTreatmentException {       
        throw new FileTreatmentException();
    }
    public Iterator iterator() throws FileTreatmentException {   
        throw new FileTreatmentException();
    }
    public String toString() {                                      
        return getName() + " (" + getSize() + ")";
    }
}

Finally, the test.

package Visitor;

public class Main {
    public static void main(String[] args) {
        try {
            System.out.println("Making root entries...");
            Directory rootdir = new Directory("root");
            Directory bindir = new Directory("bin");
            Directory tmpdir = new Directory("tmp");
            Directory usrdir = new Directory("usr");
            rootdir.add(bindir);
            rootdir.add(tmpdir);
            rootdir.add(usrdir);
            bindir.add(new File("vi", 10000));
            bindir.add(new File("latex", 20000));
            rootdir.accept(new ListVisitor());              

            System.out.println("");
            System.out.println("Making user entries...");
            Directory yuki = new Directory("yuki");
            Directory hanako = new Directory("hanako");
            Directory tomura = new Directory("tomura");
            usrdir.add(yuki);
            usrdir.add(hanako);
            usrdir.add(tomura);
            yuki.add(new File("diary.html", 100));
            yuki.add(new File("Composite.java", 200));
            hanako.add(new File("memo.tex", 300));
            tomura.add(new File("game.doc", 400));
            tomura.add(new File("junk.mail", 500));
            rootdir.accept(new ListVisitor());              
        } catch (FileTreatmentException e) {
            e.printStackTrace();
        }
    }
}

Test results.

image.png

Visitor model analysis

Let's analyze the processing flow of the visitor pattern example program, assuming a folder with two files

  • First, the main class generates the listVisitor instance.
  • The Main class calls the method of the directory class and passes in the generated listVistor instance
  • The directory's accept method calls the visitor's handler method and passes in an instance of itself.
  • Next, it comes to the listVIsitor processing flow, accessing the folder, then finding the first file in the folder and calling the accpet method on this file to access it as well, passing in an object that is an instance of its own listVIsitor
  • This is a recursive process where the listVisitor goes back to access the processing file, and then returns something like a stack when it's done
  • Then it goes back to processing the directory, and then to processing the second file, repeating the above process until there are no more objects to process and then it returns.

Role in visitor mode.

  • visitor The accessor role is responsible for declaring a corresponding visit method for each specific element in the data structure, and the concrete implementation is left to the concretevisitor
  • ConcreteVisitor Responsible for inheriting the methods that implement the visitor's access processing and implementing the specific processing logic
  • Element Indicates the object that the visitor accesses, declaring that it accepts the visitor's accept method.
  • ConcreteElemnet Responsible for implementing specific elements, the file and directory classes in the example
  • ObjectStructure Responsible for handling the collection of Elemnet elements, each Elemnet implements methods to receive visitors, so in order to access all the elements, a collection structure of all elements needs to be stored, and the directory in the instance corresponds to this.

Class diagram.

image.png


Recommended>>
1、A must see Recent Trends in Cybersecurity Breaches
2、CSIGMV HighEnd Forum on Machine Vision and Artificial Intelligence in Universities was successfully held
3、Sichuan Giant Panda Puppet makes a stunning appearance at Beijing 8 Minutes
4、Insist on innovationdriven development Made in Xiamen shines at the Fair
5、Facebook faces 2 trillion in fines Are we being manipulated under big data

    已推荐到看一看 和朋友分享想法
    最多200字,当前共 发送

    已发送

    朋友将在看一看看到

    确定
    分享你的想法...
    取消

    分享想法到看一看

    确定
    最多200字,当前共

    发送中

    网络异常,请稍后重试

    微信扫一扫
    关注该公众号