访问者模式(数据与行为解耦)

目录

前言

UML

plantuml

类图

实战代码

SimpleFileVisitor

 FileVisitor 接口

 删除指定文件夹

模板

IVisitor

IVisitable

Client


前言

一个类由成员变量和方法组成,成员变量即是类的数据结构,方法则是类的行为。

如果一个类的数据结构稳定,但是行为多变,想要增加类的行为,就必须为类添加新的方法,违背了开闭原则。

使用访问者模式,则可以在不修改原有类的前提下定义新的操作,为类增加新的行为。

它能将类的数据结构和行为解耦,将多变的行为提取到访问者中,不同的访问者实现不同的行为。当类的行为变化时,只需要替换对应的访问者就能够修改类的行为了。

故访问者特别适用于数据结构相对稳定,而操作易于变化的场景。

UML

plantuml

@startuml
'https://plantuml.com/class-diagram

interface Visitable {
    + accept(Visitor) : void
}

class ConcreteVisitable {
    + accept(Visitor) : void
}

interface Visitor {
    + visit(IVisitable) : void
}

class ConcreteVisitorA {
    + visit(IVisitable) : void
}

class ConcreteVisitorB{
    + visit(IVisitable) : void
}

class Client {}

Visitable <|.. ConcreteVisitable
Visitor <|.. ConcreteVisitorA
Visitor <|.. ConcreteVisitorB

Visitable <..> Visitor

Client ..> Visitable
Client ..> Visitor

@enduml

类图

实战代码

SimpleFileVisitor

JDK 中 nio 的 Files 的 walkFileTree 方法使用了访问者模式来遍历文件树,使用时可以重写 SimpleFileVisitor 中的方法,对文件树下每个文件做相应操作。比如删除文件,复制文件,查找文件等等。

 FileVisitor 接口

可以看到 FileVisitor 接口定义了访问文件夹的前置/后置操作,访问文件操作,以及访问文件异常操作,SimpleFileVisitor 则是提供了空实现。

在实际使用时,创建自定义文件访问者类,实现 FileVisitor 接口或者直接继承 SimpleFileVisitor 类,然后实现接口中定义的方法。使用 walkFileTree 遍历文件树时传入不同的访问者则能够对应不同的文件操作逻辑,完美地将数据结构和操作行为分离

 删除指定文件夹

public class Client {

    public static void main(String[] args) throws IOException {
        Path directory = Paths.get("/data/file/abc");
        Files.walkFileTree(directory, new SimpleFileVisitor<Path>() {
            @Override
            public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) throws IOException {
                Files.delete(file); // this will work because it's always a File
                return FileVisitResult.CONTINUE;
            }

            @Override
            public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
                Files.delete(dir); //this will work because Files in the directory are already deleted
                return FileVisitResult.CONTINUE;
            }
        });
    }

}

模板

IVisitor

public interface IVisitor {
    void visit(IVisitable visitable);
}

public class Visitor1 implements IVisitor {
    public void visit(IVisitable visitable) {
        System.out.println("Visitor1");
    }
}

public class Visitor2 implements IVisitor {
    public void visit(IVisitable visitable) {
        System.out.println("Visitor2");
    }
}

IVisitable

public interface IVisitable {
    void accept(IVisitor visitor);
}

class Part implements IVisitable {
    String name;
    Integer value;

    public void accept(IVisitor visitor) {
        visitor.visit(this);
    }
}

Client

public class Client {
    public static void main(String[] args) throws IOException {
        IVisitable part = new Part();     
    
        IVisitor visitor1 = new Visitor1();
        part.accept(visitor1);

        IVisitor visitor2 = new Visitor2();
        part.accept(visitor2);
    }
}

相关推荐

  1. 中介模式:优雅的利器

    2024-03-27 22:20:03       15 阅读
  2. 行为型设计模式访问模式

    2024-03-27 22:20:03       32 阅读
  3. 设计模式行为型设计模式——访问模式

    2024-03-27 22:20:03       16 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-03-27 22:20:03       16 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-03-27 22:20:03       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-03-27 22:20:03       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-03-27 22:20:03       18 阅读

热门阅读

  1. 【vivado】在原有工程上新建工程

    2024-03-27 22:20:03       18 阅读
  2. 【GameFramework框架内置模块】17、声音(Sound)

    2024-03-27 22:20:03       19 阅读
  3. FunASR 框架使用;api服务搭建

    2024-03-27 22:20:03       16 阅读
  4. vue中el-tree默认选中节点问题

    2024-03-27 22:20:03       18 阅读
  5. Python自动连接SSH

    2024-03-27 22:20:03       16 阅读
  6. docker centos7在线安装redis

    2024-03-27 22:20:03       15 阅读
  7. pygame制作贪吃蛇

    2024-03-27 22:20:03       17 阅读
  8. 常见typescript面试题

    2024-03-27 22:20:03       13 阅读
  9. C#基础-标识符命名规则

    2024-03-27 22:20:03       15 阅读