23 种设计模式中的访问者模式
主要用于在不改变对象结构的前提下,为对象结构中的元素添加新的操作。
访问者模式用于解决稳定数据结构和易变操作之间的耦合问题,设计的目的是不改变数据结构的定义,但允许增加新的访问者,来定义新的操作。
这里我们根据案例来具体学习访问者模式。以下是一个代码示例及知识点详解:
首先,我们要定义一个访问者接口:
// 1. 定义元素接口(被访问对象)
interface DocumentElement {
void accept(DocumentVisitor visitor); // 接受访问者的方法
}
接下来,我们需要创建具体的元素类:
// 2. 创建具体元素类
// 第一个元素类
class TextElement implements DocumentElement {
private String content;
public TextElement(String content) {
this.content = content;
}
@Override
public void accept(DocumentVisitor visitor) {
visitor.visit(this); // 双分派关键点
}
public String getContent() { return content; }
}
// 第二个元素类
class ImageElement implements DocumentElement {
private String src;
public ImageElement(String src) {
this.src = src;
}
@Override
public void accept(DocumentVisitor visitor) {
visitor.visit(this);
}
public String getSrc() { return src; }
}
接着,我们要定义访问者接口,即该访问者能够干的事情:
// 3. 定义访问者接口
interface DocumentVisitor {
void visit(TextElement text); // 重载方法处理不同元素
void visit(ImageElement image);
}
然后,我们来实现具体的访问者:
// 4. 实现具体访问者
class HTMLExportVisitor implements DocumentVisitor {
@Override
public void visit(TextElement text) {
System.out.println("<p>" + text.getContent() + "</p>");
}
@Override
public void visit(ImageElement image) {
System.out.println("<img src=\"" + image.getSrc() + "\"/>");
}
}
class MarkdownExportVisitor implements DocumentVisitor {
@Override
public void visit(TextElement text) {
System.out.println(text.getContent() + "\n");
}
@Override
public void visit(ImageElement image) {
System.out.println(" + ")");
}
}
紧接着,我们要定义一个能够持有被访问元素的数据结构
// 5. 对象结构(管理元素集合)
class Document {
private List<DocumentElement> elements = new ArrayList<>();
public void addElement(DocumentElement e) {
elements.add(e);
}
public void accept(DocumentVisitor visitor) {
for (DocumentElement e : elements) {
e.accept(visitor); // 触发访问操作
}
}
}
最后,测试下上述代码,看看客户端的执行效果:
// 客户端使用
public class VisitorDemo {
public static void main(String[] args) {
Document doc = new Document();
doc.addElement(new TextElement("Hello Visitor Pattern"));
doc.addElement(new ImageElement("diagram.jpg"));
// 不同访问者实现不同处理
doc.accept(new HTMLExportVisitor());
doc.accept(new MarkdownExportVisitor());
}
}
由此可见,访问者模式的核心思想是为了访问比较复杂的数据结构,不改变数据结构。而是把对数据的访问方式抽象出来,在访问数据的过程中以回调形式在访问者中处理操作逻辑。
如果要新增一组操作,只需要新增一个访问者。
总结
访问者模式是为了抽象出一组作用于复杂对象的操作,并且后续可以新增操作而不需要对现有的数据结构做出改动。