小白必看!浅谈Visitor访问者模式

public abstract void printList(String prefix);

public void printList(){

    printList("");

}

public Entry add(Entry entry) throws RuntimeException{

    throw new RuntimeException();

}



public Iterator iterator() throws RuntimeException{

    throw new RuntimeException();

}



@Override

public String toString() {

    return getName()+"<"+getSize()+">";

}

}


package designMode.visitor;



import sun.reflect.generics.visitor.Visitor;



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 name;

    }



    @Override

    public int getSize() {

        return size;

    }



    @Override

    public void printList(String prefix) {

        System.out.println(prefix+"/"+this);

    }



    public void accept(Visitor visitor){

        visitor.visit(this);

    }

}

package designMode.visitor;

import sun.reflect.generics.visitor.Visitor;

import java.util.ArrayList;

import java.util.Iterator;

public class Directory extends Entry {

String name;

ArrayList entrys = new ArrayList();



public Directory(String name) {

    this.name = name;

}



@Override

public String getName() {

    return name;

}



@Override

public int getSize() {

    int size = 0;

    Iterator it = entrys.iterator();

    while (it.hasNext()){

        size += ((Entry)it.next()).getSize();

    }

    return size;

}



@Override

public Entry add(Entry entry){

    entrys.add(entry);

    return this;

}



public Iterator iterator(){

    return entrys.iterator();

}



@Override

public void printList(String prefix) {

    System.out.println(prefix+"/"+this);

    Iterator it = entrys.iterator();

    Entry entry;

    while (it.hasNext()){

        entry = (Entry) it.next();

        entry.printList(prefix+"/"+name);

    }

}



public void accept(Visitor visitor){

    visitor.visit(this);

}

}


package designMode.visitor;



public abstract class Visitor {

    public abstract void visit(File file);

    public abstract void visit(Directory directory);

}

package designMode.visitor;

import java.util.Iterator;

public class ListVisitor extends Visitor {

String currentDir = "";

@Override

public void visit(File file) {

    System.out.println(currentDir+"/"+file);

}



@Override

public void visit(Directory directory) {

    System.out.println(currentDir+"/"+directory);

    String saveDir = currentDir;

    currentDir +="/"+directory.getName();

    Iterator it = directory.iterator();

    while (it.hasNext()){

        Entry entry = (Entry) it.next();

        entry.accept(this);

    }

    currentDir=saveDir;

}

}


package designMode.visitor;



import java.util.ArrayList;

import java.util.Iterator;



public class FileVisitor extends Visitor {



    String currentDir = "";

    String suffix;

    ArrayList files=new ArrayList();

    

    public FileVisitor(String suffix){

         this.suffix = suffix;

    }

    

    public void visit(File file) {

        if(file.getName().endsWith(suffix)){

         // System.out.println(currentDir+"/"+file);

            files.add(currentDir+"/"+file);

        }

    }



    public void visit(Directory directory) {

        String saveDir=currentDir;

        currentDir+=("/"+directory.getName());

        Iterator it=directory.iterator();

        while(it.hasNext()){

            Entry entry=(Entry)it.next();

            entry.accept(this);

        }

        currentDir=saveDir;

    }

    Iterator getFiles(){

        return files.iterator();

    }



}

package designMode.visitor;

import java.util.Iterator;

public class Main {

public static void main(String[] args) {



    Directory root=new Directory("根目录");

    

    Directory life=new Directory("我的生活");

    File eat=new File("吃火锅.txt",100);

    File sleep=new File("睡觉.html",100);

    File study=new File("学习.txt",100);

    life.add(eat);

    life.add(sleep);

    life.add(study);

    

    Directory work=new Directory("我的工作");

    File write=new File("写博客.doc",200);

    File paper=new File("写论文.html",200);

    File homework=new File("写家庭作业.docx",200);

    work.add(write);

    work.add(paper);

    work.add(homework);

    

    Directory relax=new Directory("我的休闲");

    File music=new File("听听音乐.js",200);

    File walk=new File("出去转转.psd",200);

    relax.add(music);

    relax.add(walk);

    

    Directory read=new Directory("我的阅读");

    File book=new File("学习书籍.psd",200);

    File novel=new File("娱乐小说.txt",200);

    read.add(book);

    read.add(novel);

    

    root.add(life);

    root.add(work);

    root.add(relax);

    root.add(read);

    

    root.accept(new ListVisitor());

    System.out.println("========================");

    FileVisitor visitor=new FileVisitor(".psd");

    root.accept(visitor);

    Iterator it = visitor.getFiles();

    while(it.hasNext()){

        System.out.println(it.next());

    }

    

}

}




![1157683-20180629170354003-2072968548.png](https://imgconvert.csdnimg.cn/aHR0cHM6Ly9pbWFnZXMyMDE4LmNuYmxvZ3MuY29tL2Jsb2cvMTE1NzY4My8yMDE4MDYvMTE1NzY4My0yMDE4MDYyOTE3MDM1NDAwMy0yMDcyOTY4NTQ4LnBuZw?x-oss-process=image/format,png)



运行结果第一个和使用Composite模式的结果一样,第二个是实现另一种方式的访问,只访问文件后缀为某一特定的内容的文件,结果也是正确的,并且为了说明我们的访问还可以保存下来访问的结果,我们使用了ArrayList自带的迭代器将保存到ArrayList中的结果输出出来,我们当然也可以直接在遍历的时候就输出出来,这个看我们的使用要求了。因此可以看到在保证数据结构不发生变化的情况下,可以非常方便增加新的一种访问方法,只需要新增加一个访问类即可,但是如果我们数据结构发生变化之后,就需要修改继承自Visitor类的所有类了,这也违背了开闭原则,因此我们应该认真考虑,到底我们的数据结构是定死的还是经常变化的。没有任何一种设计模式是十全十美的,总是有所取舍,有所利弊,根据实际情况来选择才是最好的设计方法。



这里要说明一下双重分发机制,我们来看一下最核心的遍历逻辑,结合组合模式的时候我们已经分析过遍历方法,递归,大家觉得这次我们要怎么在数据结构外面进行遍历,肯定还要使用递归,可是数据结构中的数据在类的内部,怎么递归到内部呢,我们想到了间接递归,也就是双重分发。



public void printList(String prefix) {

    System.out.println(prefix+"/"+this);

读者福利

分享一份自己整理好的Java面试手册,还有一些面试题pdf

领取方式;关注+点赞后,戳这里即可免费领取

不要停下自己学习的脚步

字节跳动的面试分享,为了拿下这个offer鬼知道我经历了什么

字节跳动的面试分享,为了拿下这个offer鬼知道我经历了什么

模式是十全十美的,总是有所取舍,有所利弊,根据实际情况来选择才是最好的设计方法。

这里要说明一下双重分发机制,我们来看一下最核心的遍历逻辑,结合组合模式的时候我们已经分析过遍历方法,递归,大家觉得这次我们要怎么在数据结构外面进行遍历,肯定还要使用递归,可是数据结构中的数据在类的内部,怎么递归到内部呢,我们想到了间接递归,也就是双重分发。


public void printList(String prefix) {

        System.out.println(prefix+"/"+this);


# **读者福利**

分享一份自己整理好的Java面试手册,还有一些面试题pdf

**[领取方式;关注+点赞后,戳这里即可免费领取](https://gitee.com/vip204888/java-p7)**

**不要停下自己学习的脚步**

[外链图片转存中...(img-tpYpwXet-1628149945225)]

[外链图片转存中...(img-N3l1RGpy-1628149945228)]

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值