图解设计模式-Visitor模式

Visitor模式即访问者模式
在数据结构中保存许多元素,我们会对这些元素进行处理,这时“处理”代码放在那里比较好?通常的做法是将它们放在表示数据结构中的类中。但是,如果“处理”有许多中那?这种情况下,没当增加一种处理时,我们就不得不去修改表示数据结构的类。
Visitor模式中将数据结构与处理分离开。
 
角色:
Visitor访问者:负责对数据结构中的每个具体元素声明一个用于访问XXXX的visitor(XXXX)方法。visitor(XXXX)用于处理XXXX的方法,负责实现该方法的是ConcreteVisitor角色,本示例中由Visitor类扮演。
ConcreteVisitor具体的访问者:负责实现Visitor角色所定义的接口ApI。它要实现所有的visitor(XXXX)方法,即实现如何处理每个ConcreteElement角色。在本示例中,有ListVisitor类扮演。
Element元素:表示Visitor角色的访问对象。它声明了介绍访问者的accept方法,accept方法接受到的参数为Visitor角色,本示例中由Element类扮演。
ConcreteElement具体元素:负责实现Element角色所定义的接口API。
Constructure对象结构:负责处理Element角色的集合。ConcreteVisitor角色为每个Element角色都准备了处理方法。
 
代码:
public abstract class Visitor {
    public abstract void visitor(File file);
    public abstract void visitor(Directory directory);
}
public interface Element {
    public abstract void accept(Visitor visitor);
}
public abstract class Entry implements Element {
    public abstract String getName();
    public abstract int getSize();
    public Entry add(Entry entry) throws Exception {
        throw new Exception("add");
    }

    public Iterator iterator() throws Exception {
        throw new Exception("iterator");
    }

    @Override
    public String toString() {
        return getName() + "("+getSize()+")";
    }
}
public class File extends Entry {
    private String name;
    private int size;
    public File(String name,int size) {
        this.name = name;
        this.size = size;
    }
    @Override
    public String getName() {
        return this.name;
    }

    @Override
    public int getSize() {
        return this.size;
    }

    @Override
    public void accept(Visitor visitor) {
        visitor.visitor(this);
    }
}
public class Directory extends Entry {
    private String name;
    private ArrayList<Entry> dir = new ArrayList<>();

    public Directory(String name) {
        this.name = name;
    }

    @Override
    public String getName() {
        return this.name;
    }

    @Override
    public int getSize() {
        int size = 0;
        for(Entry entry:dir) {
            size +=entry.getSize();
        }
        return size;
    }
    public Entry add(Entry entry) {
        dir.add(entry);
        return this;
    }

    public Iterator iterator() {
        return dir.iterator();
    }

    @Override
    public void accept(Visitor visitor) {
        visitor.visitor(this);
    }
}
public class ListVisitor extends Visitor {
    private String currentDir = "";

    @Override
    public void visitor(File file) {
        System.out.println(currentDir + "/" +file.getName());
    }

    @Override
    public void visitor(Directory directory) {
        System.out.println(currentDir + "/" +directory.getName());
        String savedir = currentDir;
        currentDir = currentDir + "/" +directory.getName();
        Iterator iterator = directory.iterator();
        while(iterator.hasNext()) {
            Entry entry = (Entry) iterator.next();
            entry.accept(this);
        }
        currentDir = savedir;
    }
}
public class Main {
    public static void main(String[] args) {
        try {
            Directory rootDir = new Directory("root");
            Directory binDir = new Directory("bin");
            Directory tempDir = new Directory("temp");
            Directory userDir = new Directory("user");
            rootDir.add(binDir);
            rootDir.add(tempDir);
            rootDir.add(userDir);
            binDir.add(new File("vi",1000));
            binDir.add(new File("latex",2000));
            rootDir.accept(new ListVisitor());

        }catch (Exception ex){
            ex.printStackTrace();
        }
    }
}
执行结果:
/root
/root/bin
/root/bin/vi
/root/bin/latex
/root/temp
/root/us
posted @ 2018-09-09 23:46  使用D  阅读(474)  评论(0编辑  收藏  举报