1、简述
访问者模式(Visitor Pattern)是一种行为型设计模式,允许你将操作分离到不同的对象中,而无需修改对象本身的结构。这种模式特别适合复杂对象结构中对其元素进行操作的场景。
设计模式样例:https://gitee.com/lhdxhl/design-pattern-example.git
本文将介绍访问者模式的核心概念、优缺点,并通过详细代码示例展示如何在实际应用中实现访问者模式。
2、什么是访问者模式?
访问者模式的核心思想是:
- 将数据结构和操作分离:操作以访问者对象的形式定义,而不是嵌入在被操作的类中。
- 扩展性强:当需要添加新的操作时,只需创建新的访问者类,而无需修改原有数据结构。
访问者模式由以下几个核心角色组成:
- 访问者接口(Visitor):声明对元素进行操作的方法。
- 具体访问者(Concrete Visitor):实现访问者接口,定义具体的操作。
- 元素接口(Element):定义接受访问者的方法(
accept
)。 - 具体元素(Concrete Element):实现元素接口,提供具体的数据结构。
- 对象结构(Object Structure):维护一组元素,并允许访问者访问这些元素。
3、实际案例
假设我们有一个公司的人员管理系统,需要对不同员工的薪资进行调整。不同类型的员工有不同的调整规则。我们可以使用访问者模式实现这一功能。
import java.util.ArrayList;
import java.util.List;
// 访问者接口
public interface Visitor {
void visit(Manager manager);
void visit(Developer developer);
}
// 具体访问者:薪资调整
public class SalaryAdjustmentVisitor implements Visitor {
@Override
public void visit(Manager manager) {
System.out.println("Adjusting salary for Manager: " + manager.getName());
manager.setSalary(manager.getSalary() * 1.10);
}
@Override
public void visit(Developer developer) {
System.out.println("Adjusting salary for Developer: " + developer.getName());
developer.setSalary(developer.getSalary() * 1.20);
}
}
// 元素接口
public interface Employee {
void accept(Visitor visitor);
String getName();
double getSalary();
void setSalary(double salary);
}
// 具体元素:经理
public class Manager implements Employee {
private String name;
private double salary;
public Manager(String name, double salary) {
this.name = name;
this.salary = salary;
}
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
@Override
public String getName() {
return name;
}
@Override
public double getSalary() {
return salary;
}
@Override
public void setSalary(double salary) {
this.salary = salary;
}
}
// 具体元素:开发者
public class Developer implements Employee {
private String name;
private double salary;
public Developer(String name, double salary) {
this.name = name;
this.salary = salary;
}
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
@Override
public String getName() {
return name;
}
@Override
public double getSalary() {
return salary;
}
@Override
public void setSalary(double salary) {
this.salary = salary;
}
}
// 对象结构
public class Company {
private List<Employee> employees = new ArrayList<>();
public void addEmployee(Employee employee) {
employees.add(employee);
}
public void accept(Visitor visitor) {
for (Employee employee : employees) {
employee.accept(visitor);
}
}
}
// 测试类
public class VisitorPatternDemo {
public static void main(String[] args) {
// 创建员工
Manager manager = new Manager("Alice", 5000);
Developer developer = new Developer("Bob", 3000);
// 创建公司
Company company = new Company();
company.addEmployee(manager);
company.addEmployee(developer);
// 创建访问者
SalaryAdjustmentVisitor salaryAdjustmentVisitor = new SalaryAdjustmentVisitor();
// 调整薪资
company.accept(salaryAdjustmentVisitor);
// 输出调整后薪资
System.out.println(manager.getName() + "'s new salary: " + manager.getSalary());
System.out.println(developer.getName() + "'s new salary: " + developer.getSalary());
}
}
输出:
Adjusting salary for Manager: Alice
Adjusting salary for Developer: Bob
Alice's new salary: 5500.0
Bob's new salary: 3600.0
4、访问者模式的优缺点
优点
- 开闭原则:可以在不修改数据结构的情况下增加新的操作。
- 操作聚合:将操作封装到访问者中,便于管理和扩展。
- 灵活性高:同一个访问者可以在不同对象上实现不同的操作。
缺点
- 对象结构依赖性:数据结构的变化可能导致访问者需要修改。
- 违反单一职责原则:访问者承担了多个对象的操作职责。
- 复杂性增加:增加了代码的复杂性。
5、应用场景
- 编译器:对语法树的不同节点执行不同操作(如语义分析、代码生成等)。
- 报表生成:对不同类型的数据执行特定的计算和格式化操作。
- 复杂对象结构:需要对对象结构中的不同类型对象进行多种操作。
6、总结
访问者模式是一种强大的设计模式,特别适合需要对复杂对象结构进行多种操作的场景。它通过将操作与对象分离,实现了良好的扩展性。在实际开发中,可以根据具体需求灵活应用访问者模式。
希望本文能帮助您更好地理解和运用访问者模式!如果有问题或建议,欢迎留言交流!
评论区