访问者模式适用于对象结构稳定但操作频繁变化的场景,其核心是将操作从数据结构中分离。1.当需要对树形或复杂对象结构执行多种不同操作且操作类型常变时使用;2.通过定义访问者接口封装各类操作,保持对象结构不变;3.示例代码中employee接口及其实现类通过accept方法接受访问者,visitor接口实现具体计算逻辑;4.优点包括遵循单一职责与开闭原则,缺点是增加复杂性、依赖结构稳定并可能破坏封装;5.典型应用于编译器对抽象语法树的操作,如类型检查、代码生成等;6.避免过度使用,若结构不稳定或操作固定则应选择策略、模板方法等其他模式。
访问者模式,简单来说,就是把作用于某种数据结构(比如对象集合)上的操作,从数据结构本身分离出来,放到一个独立的“访问者”对象里。这样做的好处是,可以让你在不修改数据结构的前提下,增加新的操作。
访问者模式的核心在于将算法与它所作用的对象结构分离。
当你需要对一个对象结构(比如树形结构,或者一个复杂的对象图)中的对象执行多种不同的操作,并且这些操作的类型经常改变时,访问者模式就派上用场了。想象一下,你有一个表示公司组织架构的树,你可能需要计算每个部门的薪资总额,或者找出所有员工的绩效等级。如果这些计算逻辑都写在部门和员工的类里,那代码会变得非常臃肿,而且每次增加新的计算逻辑,都要修改这些类。访问者模式允许你将这些计算逻辑封装到独立的访问者类中,从而保持对象结构的稳定。
立即学习“Java免费学习笔记(深入)”;
假设我们有一个 Employee 接口和两个实现类 Developer 和 Manager。
interface Employee { void accept(Visitor visitor); String getName(); double getSalary(); } 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; } } 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; } }
现在,我们定义一个 Visitor 接口和一个实现类 SalaryVisitor,用于计算所有员工的工资总额。
interface Visitor { void visit(Developer developer); void visit(Manager manager); double getTotalSalary(); } class SalaryVisitor implements Visitor { private double totalSalary = 0; @Override public void visit(Developer developer) { totalSalary += developer.getSalary(); } @Override public void visit(Manager manager) { totalSalary += manager.getSalary(); } @Override public double getTotalSalary() { return totalSalary; } }
最后,我们可以这样使用:
public class Main { public static void main(String[] args) { List<Employee> employees = new ArrayList<>(); employees.add(new Developer("Alice", 70000)); employees.add(new Manager("Bob", 100000)); SalaryVisitor salaryVisitor = new SalaryVisitor(); for (Employee employee : employees) { employee.accept(salaryVisitor); } System.out.println("Total salary: " + salaryVisitor.getTotalSalary()); } }
这段代码的关键在于 accept 方法,它接受一个 Visitor 对象,并调用 Visitor 对象的 visit 方法,将自身传递给 Visitor。这样,Visitor 就可以访问 Employee 对象的属性,并执行相应的操作。
优点很明显:
缺点也不容忽视:
访问者模式经常与迭代器模式和组合模式一起使用。迭代器模式用于遍历对象结构,组合模式用于表示树形结构。访问者模式可以对迭代器遍历的对象结构执行操作,或者对组合模式表示的树形结构执行操作。
另外,访问者模式和策略模式也容易混淆。策略模式关注的是算法的切换,而访问者模式关注的是对对象结构的操作。策略模式通常用于解决同一类问题,但使用不同的算法;访问者模式通常用于解决不同类型的问题,但作用于相同的对象结构。
编译器和解释器是访问者模式的典型应用场景。编译器需要对抽象语法树(AST)进行多种操作,比如类型检查、代码优化、代码生成等。每种操作都可以封装到一个独立的访问者类中。这样做的好处是,可以很容易地增加新的操作,而不需要修改 AST 的结构。
例如,你可以有一个 TypeCheckerVisitor 用于类型检查,一个 CodeOptimizerVisitor 用于代码优化,一个 CodeGeneratorVisitor 用于代码生成。每个访问者都负责一种操作,并且可以独立地进行修改和扩展。
访问者模式虽然强大,但也不是万能的。过度使用访问者模式会导致代码的复杂性增加,维护成本升高。因此,在使用访问者模式之前,需要仔细评估其适用性。
一个简单的原则是:如果对象结构相对稳定,但操作类型经常变化,那么可以考虑使用访问者模式。反之,如果对象结构经常变化,或者操作类型相对稳定,那么就应该避免使用访问者模式。
另外,还可以考虑使用其他的设计模式,比如策略模式、模板方法模式等,来解决类似的问题。选择哪种模式,取决于具体的应用场景和需求。
以上就是Java中访问者的用法_Java中访问者模式的实践的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号