Visitor访问者模式应用之Files.FileWalkTree

这篇博客探讨了在Java中如何利用访问者模式(Visitor Pattern)来遍历文件系统,特别是在`walkFileTree()`函数中应用。通过重写访问者方法,用户可以在访问文件和目录前后执行自定义操作,例如在删除目录前先删除其中的文件。这种模式类似于模板方法,提供了在不修改原始对象结构的情况下扩展功能的方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

访问者,顾名思义,就是对象访问的一种设计模式,我们可以在不改变要访问对象的前提下,对访问对象的操作做拓展,包括访问前,访问中,访问后

public static void main(String[] args) throws IOException {
        //由于匿名内部类只能访问不变变量,即final,因此使用原子整数计数
        AtomicInteger fileCount = new AtomicInteger();
        AtomicInteger dirCount = new AtomicInteger();
        Files.walkFileTree(Paths.get("D:\\nginx\\nginx-1.22.0"), new SimpleFileVisitor<Path>() {
            @Override
            public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
                System.out.println("目录:" + dir);
                dirCount.getAndIncrement();
                return super.preVisitDirectory(dir, attrs);
            }

            @Override
            public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
                System.out.println("文件:" + file);
                fileCount.getAndIncrement();
                return super.visitFile(file, attrs);
            }
        });
        System.out.println("目录数:"+dirCount.get());
        System.out.println("文件数:"+fileCount.get());
    }

walkFileTree()传入的第二个参数是访问者,用户可以根据自己的选择重写其中的方法,包括访问目录之前,访问文件时,访问目录之后,按需求访问文件

 源码:

switch (ev.type()) {
                    case ENTRY :
                        IOException ioe = ev.ioeException();
                        if (ioe == null) {
                            assert ev.attributes() != null;
                            result = visitor.visitFile(ev.file(), ev.attributes());
                        } else {
                            result = visitor.visitFileFailed(ev.file(), ioe);
                        }
                        break;

                    case START_DIRECTORY :
                        result = visitor.preVisitDirectory(ev.file(), ev.attributes());

                        // if SKIP_SIBLINGS and SKIP_SUBTREE is returned then
                        // there shouldn't be any more events for the current
                        // directory.
                        if (result == FileVisitResult.SKIP_SUBTREE ||
                            result == FileVisitResult.SKIP_SIBLINGS)
                            walker.pop();
                        break;

                    case END_DIRECTORY :
                        result = visitor.postVisitDirectory(ev.file(), ev.ioeException());

                        // SKIP_SIBLINGS is a no-op for postVisitDirectory
                        if (result == FileVisitResult.SKIP_SIBLINGS)
                            result = FileVisitResult.CONTINUE;
                        break;

对文件类型进行选择:

  1. 如果是文件,则执行 visitor.visitFile(),visitor.visitFileFailed()方法

  2. 如果是目录的起始点,则执行visitor.preVisitDirectory()

  3. 如果是目录的结尾,则执行visitor.postVisitDirectory()

如果用户不重写方法,则执行默认的方法体或者空方法,像实现哪个部分的功能就重写哪个方法

实现删除有文件的目录:

由于Files.delete不能删除有文件的目录,所以可以借助访问者先删除目录中的文件,再到访问完目录时,删除目录

public static void main(String[] args) throws IOException {
        Files.walkFileTree(Paths.get("D:\\nginx\\nginx-1.22.0"), new SimpleFileVisitor<Path>() {

            @Override
            public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
                Files.delete(file);
                return super.visitFile(file, attrs);
            }

            @Override
            public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
                Files.delete(dir);
                return super.postVisitDirectory(dir, exc);
            }
        });
    }

有点类似模板方法,对比:

  • 模板方法实现了对同一类型的功能的自定义扩展,比如用户自己添加想要的AutowiredBeanPostProcessor

  • 而访问者模式实现了对不同功能的拓展,也是事先准备好对应的默认方法,用户自己重写对应的方法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值