访问者(Visitor)设计模式用于在不改变对象结构的情况下,定义对象的新操作。
访问者(Visitor)模式允许我们在不更改对象结构的情况下,向一组对象应用新的操作。它将操作封装在一个访问者对象中,使得我们可以对不同类型的对象应用不同的操作,而无需在对象内部定义这些操作。
访问者(Visitor)模式适用于以下情况:
下面是一个示例,我们将使用访问者模式来对不同类型的员工对象进行不同的薪资计算操作。我们先定义一个员工接口和三个具体的员工类,然后定义一个访问者接口和两个具体的访问者类来计算不同类型员工的薪资。下面是代码实现:
// 员工接口
interface Employee {
void accept(Visitor visitor); // 接受访问者
}
// 具体员工类:全职员工
class FullTimeEmployee implements Employee {
private String name;
private double monthlySalary;
public FullTimeEmployee(String name, double monthlySalary) {
this.name = name;
this.monthlySalary = monthlySalary;
}
public String getName() {
return name;
}
public double getMonthlySalary() {
return monthlySalary;
}
public void accept(Visitor visitor) {
visitor.visit(this);
}
}
// 具体员工类:临时员工
class PartTimeEmployee implements Employee {
private String name;
private double hourlySalary;
private int workedHours;
public PartTimeEmployee(String name, double hourlySalary, int workedHours) {
this.name = name;
this.hourlySalary = hourlySalary;
this.workedHours = workedHours;
}
public String getName() {
return name;
}
public double getHourlySalary() {
return hourlySalary;
}
public int getWorkedHours() {
return workedHours;
}
public void accept(Visitor visitor) {
visitor.visit(this);
}
}
// 访问者接口
interface Visitor {
void visit(FullTimeEmployee employee); // 访问全职员工
void visit(PartTimeEmployee employee); // 访问临时员工
}
// 具体访问者类:计算全职员工薪资
class FullTimeSalaryVisitor implements Visitor {
public void visit(FullTimeEmployee employee) {
double salary = employee.getMonthlySalary();
System.out.println("全职员工 " + employee.getName() + " 的薪资为: " + salary);
}
public void visit(PartTimeEmployee employee) {
// 不计算临时员工薪资
}
}
// 具体访问者类:计算临时员工薪资
class PartTimeSalaryVisitor implements Visitor {
public void visit(FullTimeEmployee employee) {
// 不计算全职员工薪资
}
public void visit(PartTimeEmployee employee) {
double salary = employee.getHourlySalary() * employee.getWorkedHours();
System.out.println("临时员工 " + employee.getName() + " 的薪资为: " + salary);
}
}
// 客户端代码
public class Client {
public static void main(String[] args) {
Employee[] employees = new Employee[]{
new FullTimeEmployee("张三", 5000),
new PartTimeEmployee("李四", 20, 80)
};
Visitor fullTimeSalaryVisitor = new FullTimeSalaryVisitor();
Visitor partTimeSalaryVisitor = new PartTimeSalaryVisitor();
for (Employee employee : employees) {
employee.accept(fullTimeSalaryVisitor);
employee.accept(partTimeSalaryVisitor);
}
}
}
在上述代码中,我们定义了一个员工接口(Employee),其中包含了一个接受访问者的方法。然后我们创建了两个具体的员工类:全职员工(FullTimeEmployee)和临时员工(PartTimeEmployee),它们实现了员工接口。
接下来,我们定义了一个访问者接口(Visitor),包含了不同类型员工的访问方法。然后创建了两个具体的访问者类:计算全职员工薪资的访问者(FullTimeSalaryVisitor)和计算临时员工薪资的访问者(PartTimeSalaryVisitor)。
在客户端代码中,我们创建了一组员工对象,并创建了两个访问者对象。然后,使用循环遍历每个员工对象,并分别接受全职员工和临时员工的访问者,进行薪资计算操作。
运行上述代码,您应该会得到以下输出结果:
全职员工 张三 的薪资为: 5000.0
临时员工 李四 的薪资为: 1600.0
这是因为我们使用访问者模式,根据不同类型的员工对象,应用了不同的薪资计算操作。
Java源码中的扩展Visitor模式:Java中的语法树(抽象语法树)工具包(javax.lang.model包)使用了Visitor模式来处理语法树中的不同类型的节点。它定义了Element接口和对应的一组Visitor接口,开发者可以根据自己的需求实现相应的Visitor类来对语法树节点进行处理。
Apache Lucene:Lucene是一个开源的全文搜索引擎库。在Lucene中,用于索引和搜索的各种类(如Field、Query等)都实现了一组访问者接口(FieldVisitor、QueryVisitor等),通过访问者模式来进行索引和搜索的操作。
Hibernate框架中的映射(Mapping):Hibernate是一个ORM(对象关系映射)框架,它通过映射文件将Java对象映射到数据库表中。在映射文件中,可以使用Visitor模式来访问不同类型的映射元素,完成对应的处理逻辑。
Apache Maven:Maven是一个Java项目管理工具,它使用了访问者模式来遍历项目的目录结构和依赖关系,执行各种构建和部署任务。Maven中使用了一组访问者接口(Visitor)和相应的访问者实现类来对项目进行处理。
访问者(Visitor)模式是一种行为型设计模式,它允许我们在不更改对象结构的情况下,向一组对象应用新的操作。通过将操作封装在访问者对象中,我们可以对不同类型的对象应用不同的操作,而无需在对象内部定义这些操作。访问者模式适用于需要对一组对象进行类似操作的场景,并且希望避免修改对象类的情况。在实际开发中,我们可以使用访问者模式来添加新的操作,而无需修改对象类的代码。
关注微信公众号:“小虎哥的技术博客”。我们会定期发布关于Java技术的详尽文章,让您能够深入了解该领域的各种技巧和方法,让我们一起成为更优秀的程序员!