目录
访问者模式的定义
访问者模式(Visitor Pattern)属于行为型设计模式,它允许在不修改现有对象结构的前提下,定义对这些对象执行操作的新操作。访问者模式将数据结构和操作分离,使得操作可以独立变化。
访问者模式基本思想是,针对系统中拥有固定类型数的对象结构(元素),在其内提供一个 accept()方法来接受访问者对象的访问。不同的访问者对同一个元素的访问内容是不同,使得相同的元素集合可以产生不同的数据结果。
访问者模式的实现
访问者模式角色
- 抽象访问者角色(Visitor):接口或者抽象类,为该对象结构中具体元素角色声明一个访问操作接口。该操作接口的名字和参数标识了发送访问请求给具体访问者的具体元素角色,这样访问者就可以通过该元素角色的特定接口直接访问它。
- 具体访问者角色(ConcreteVisitor):实现Visitor声明的接口,是每个操作实现的部分。
- 抽象元素角色(Element):接口或者抽象类,该类定义了一个接受访问者访问的方法 accept()方法,表示所有元素类型都支持被访问者访问。
- 具体元素角色(ConcreteElement):具体元素类型,实现了抽象元素(Element)所定义的接受操作接口。
- 结构对象角色(ObjectStructure):该类内部维护了元素集合,并提供方法接受访问者对该集合所有元素进行操作。它具备以下特性:能枚举它的元素;可以提供一个高层接口以允许访问者访问它的元素;如有需要,可以设计成一个复合对象或者一个聚集(如一个列表或无序集合)。
访问者模式类图
访问者模式代码实现
抽象访问者角色
package com.common.demo.pattern.visitor;
/**
* @author Evan Walker 昂焱数据: https://www.ayshuju.com
* @version 1.0
* @desc 抽象访问者角色
* @date 2023/08/09 21:48:44
*/
public interface ComputerPartVisitor {
void visit(ComputerHost computerHost);
void visit(Mouse mouse);
void visit(Keyboard keyboard);
void visit(Monitor monitor);
}
具体访问者角色
package com.common.demo.pattern.visitor;
/**
* @author Evan Walker 昂焱数据: https://www.ayshuju.com
* @version 1.0
* @desc 实体访问者角色 计算机部件显示访问者
* @date 2023/08/09 21:54:19
*/
public class ComputerPartDisplayVisitor implements ComputerPartVisitor{
@Override
public void visit(ComputerHost computerHost) {
System.out.println("Displaying Computer.");
}
@Override
public void visit(Mouse mouse) {
System.out.println("Displaying Mouse.");
}
@Override
public void visit(Keyboard keyboard) {
System.out.println("Displaying Keyboard.");
}
@Override
public void visit(Monitor monitor) {
System.out.println("Displaying Monitor.");
}
}
抽象元素角色
package com.common.demo.pattern.visitor;
/**
* @author Evan Walker 昂焱数据: https://www.ayshuju.com
* @version 1.0
* @desc 抽象元素角色 计算机组成部分
* @date 2023/08/09 21:47:18
*/
public interface ComputerPart {
void accept(ComputerPartVisitor computerPartVisitor);
}
具体元素角色
package com.common.demo.pattern.visitor;
/**
* @author Evan Walker 昂焱数据: https://www.ayshuju.com
* @version 1.0
* @desc 具体元素角色 电脑主机
* @date 2023/08/09 21:50:15
*/
public class ComputerHost implements ComputerPart {
@Override
public void accept(ComputerPartVisitor computerPartVisitor) {
computerPartVisitor.visit(this);
}
}
package com.common.demo.pattern.visitor;
/**
* @author Evan Walker 昂焱数据: https://www.ayshuju.com
* @version 1.0
* @desc 具体元素角色 键盘
* @date 2023/08/09 21:50:15
*/
public class Keyboard implements ComputerPart {
@Override
public void accept(ComputerPartVisitor computerPartVisitor) {
computerPartVisitor.visit(this);
}
}
package com.common.demo.pattern.visitor;
/**
* @author Evan Walker 昂焱数据: https://www.ayshuju.com
* @version 1.0
* @desc 具体元素角色 显示器
* @date 2023/08/09 21:50:15
*/
public class Monitor implements ComputerPart {
@Override
public void accept(ComputerPartVisitor computerPartVisitor) {
computerPartVisitor.visit(this);
}
}
package com.common.demo.pattern.visitor;
/**
* @author Evan Walker 昂焱数据: https://www.ayshuju.com
* @version 1.0
* @desc 具体元素角色 鼠标
* @date 2023/08/09 21:50:15
*/
public class Mouse implements ComputerPart {
@Override
public void accept(ComputerPartVisitor computerPartVisitor) {
computerPartVisitor.visit(this);
}
}
结构对象角色
package com.common.demo.pattern.visitor;
import java.util.ArrayList;
import java.util.List;
/**
* @author Evan Walker 昂焱数据: https://www.ayshuju.com
* @version 1.0
* @desc 结构对象角色 电脑
* @date 2023/08/09 21:50:15
*/
public class Computer{
private List<ComputerPart> employeeList = new ArrayList<>();
{
employeeList.add(new ComputerHost());
employeeList.add(new Keyboard());
employeeList.add(new Monitor());
employeeList.add(new Mouse());
}
//遍历
public void showReport(ComputerPartVisitor visitor){
for (ComputerPart computerPart : this.employeeList) {
computerPart.accept(visitor);
}
}
}
测试代码
package com.common.demo.pattern.visitor;
/**
* @author Evan Walker 昂焱数据: https://www.ayshuju.com
* @version 1.0
* @desc 测试代码
* @date 2023/08/09 22:00:44
*/
public class Test {
public static void main(String[] args) {
Computer computer = new Computer();
computer.showReport(new ComputerPartDisplayVisitor());
}
}
测试截图
访问者模式的特点
优点
- 增加新的操作更容易:通过访问者模式,可以在不修改现有对象结构的情况下增加新的操作,符合开闭原则。
- 将相关操作集中到一个访问者类中:访问者模式将相关操作封装在一个访问者类中,使得代码更加结构化和清晰。
- 扩展性强:由于访问者模式将数据结构和操作解耦,因此可以方便地添加新的数据结构和操作,扩展性强。
- 解耦性:解耦了数据结构与数据操作,使得操作集合可以独立变化。
缺点
- 增加新的元素类困难:当需要增加新的元素类时,需要同时修改访问者接口和所有的具体访问者类,可能导致修改的范围较大。
- 违反了单一职责原则:访问者模式将相关操作集中到访问者类中,可能导致该类承担过多的责任,违反单一职责原则。
- 违背依赖倒置原则:访问者角色依赖的是具体元素类型,而不是抽象。
使用场景
- 当需要对一组对象执行多种不同且不相关的操作时,可以考虑使用访问者模式。
- 数据结构稳定,数据结构与数据操作分离,作用于数据结构的操作经常变化的场景。
注意事项
- 对象结构稳定:在使用访问者模式时,对象结构应该是相对稳定的,避免频繁修改对象结构,否则会导致访问者接口和具体访问者类的修改范围较大。
- 具体元素类的扩展:如果需要频繁添加新的元素类,可能会增加访问者接口和具体访问者类的修改工作量,需要谨慎设计。
实际应用
- 编译器的语法树分析:编译器可以使用访问者模式来遍历语法树,对不同类型的节点执行不同的操作。
- 数据结构的序列化:对于复杂的数据结构,可以使用访问者模式来实现序列化操作,将对象转换为特定格式的字符串或字节流。
更多消息资讯,请访问昂焱数据(https://www.ayshuju.com)