目录
前言
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);
}
}