访问者模式是一种行为型设计模式,它可以在不修改现有代码结构的情况下,为复杂的对象结构添加新的操作。该模式将数据结构和数据操作进行分离,使得数据结构可以独立于操作进行变化,同时也可以在不改变操作的前提下增加新的操作。
在访问者模式中,主要有以下几个角色:
① 访问者(Visitor):定义了对每个元素对象访问时所要执行的操作,可以通过多态实现针对不同元素的不同操作。
② 具体访问者(ConcreteVisitor):实现了访问者定义的接口,完成对元素对象的具体操作。
③ 元素(Element):定义了一个 `accept` 方法,用于接受访问者的访问。
④ 具体元素(ConcreteElement):实现了元素定义的接口,通常会在 `accept` 方法中调用访问者的方法。
⑤ 对象结构(ObjectStructure):包含一个元素的集合,通常提供一个方法让访问者遍历所有元素。
访问者模式适用于对象结构比较稳定,但经常需要在此对象结构上定义新的操作的情况,或者有复杂的对象结构需要一些独立的操作的情况。
1、场景设计
实现场景:对象结构中定义A、B两个元素,访问者对它们进行访问。
2、C++实现
`Visitor` 是抽象访问者类,`ConcreteVisitor` 是具体访问者类,`Element` 是抽象元素类,`ConcreteElementA` 和 `ConcreteElementB` 是具体元素类。`ObjectStructure` 是对象结构类,包含了一个元素的集合,可以接受访问者的访问。在 `main` 函数中,我们创建了一个具体的访问者和一个对象结构,然后向对象结构中添加了两个具体元素,最后让访问者访问对象结构。
#include <iostream>
#include <vector>
// 前置声明,防止循环引用
class ConcreteElementB;
// 抽象访问者类
class Visitor {
public:
virtual void visit(ConcreteElementB* element) = 0;
};
// 具体访问者类
class ConcreteVisitor : public Visitor {
public:
void visit(ConcreteElementB* element) override {
std::cout << "ConcreteVisitor is visiting ConcreteElementB" << std::endl;
}
};
// 抽象元素类
class Element {
public:
virtual void accept(Visitor* visitor) = 0;
};
// 具体元素类A
class ConcreteElementA : public Element {
public:
void accept(Visitor* visitor) override {
std::cout << "ConcreteElementA is accepting visitor" << std::endl;
}
};
// 具体元素类B
class ConcreteElementB : public Element {
public:
void accept(Visitor* visitor) override {
visitor->visit(this);
}
};
// 对象结构类
class ObjectStructure {
private:
std::vector<Element*> elements;
public:
void addElement(Element* element) {
elements.push_back(element);
}
void accept(Visitor* visitor) {
for (Element* element : elements) {
element->accept(visitor);
}
}
};
int main() {
ConcreteVisitor visitor;
ObjectStructure objectStructure;
ConcreteElementA elementA;
ConcreteElementB elementB;
objectStructure.addElement(&elementA);
objectStructure.addElement(&elementB);
objectStructure.accept(&visitor);
return 0;
}
3、Java实现
`Visitor` 是抽象访问者类,`ConcreteVisitor` 是具体访问者类,`Element` 是抽象元素类,`ConcreteElementA` 和 `ConcreteElementB` 是具体元素类。`ObjectStructure` 是对象结构类,包含了一个元素的集合,可以接受访问者的访问。在 `main` 方法中,我们创建了一个具体的访问者和一个对象结构,向对象结构中添加了两个具体元素,并让访问者访问对象结构。
package behavioralpattern.visitor;
import java.util.ArrayList;
import java.util.List;
// 抽象访问者类
interface Visitor {
void visit(ConcreteElementB element);
}
// 具体访问者类
class ConcreteVisitor implements Visitor {
@Override
public void visit(ConcreteElementB element) {
System.out.println("ConcreteVisitor is visiting ConcreteElementB");
}
}
// 抽象元素类
interface Element {
void accept(Visitor visitor);
}
// 具体元素类A
class ConcreteElementA implements Element {
@Override
public void accept(Visitor visitor) {
System.out.println("ConcreteElementA is accepting visitor");
}
}
// 具体元素类B
class ConcreteElementB implements Element {
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
}
// 对象结构类
class ObjectStructure {
private List<Element> elements = new ArrayList<>();
public void addElement(Element element) {
elements.add(element);
}
public void accept(Visitor visitor) {
for (Element element : elements) {
element.accept(visitor);
}
}
}
public class VisitorDemo {
public static void main(String[] args) {
ConcreteVisitor visitor = new ConcreteVisitor();
ObjectStructure objectStructure = new ObjectStructure();
ConcreteElementA elementA = new ConcreteElementA();
ConcreteElementB elementB = new ConcreteElementB();
objectStructure.addElement(elementA);
objectStructure.addElement(elementB);
objectStructure.accept(visitor);
}
}