当前位置: 首页 > news >正文

0132_访问者模式(Visitor)

访问者模式(Visitor)

意图

表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。

UML 图

Visitor

优点

  1. 开闭原则:容易添加新的访问者操作,无需修改元素类
  2. 单一职责原则:将相关行为集中到一个访问者对象中
  3. 灵活性:可以在运行时选择不同的访问者执行不同的操作
  4. 数据分离:访问者可以收集复杂的对象结构信息
  5. 扩展性好:新增访问者不会影响现有系统结构

缺点

  1. 元素接口变更困难:每增加一个新的元素类,都要在访问者接口中添加一个新的visit操作
  2. 破坏封装性:访问者通常需要访问元素的内部状态,可能破坏封装性
  3. 依赖具体类:访问者依赖具体元素类,而不是抽象接口
  4. 对象结构变化困难:如果对象结构经常变化,会导致需要修改所有访问者

代码示例

以人类和机器人的诊断维护系统为例:

1. 访问者接口 (Visitor)

// 访问者接口
public interface Visitor {void visitHuman(Human human);void visitRobot(Robot robot);String getReport();
}

2. 具体访问者类 (Concrete Visitors)

// 健康检查访问者
public class HealthCheckVisitor implements Visitor {private StringBuilder report = new StringBuilder();@Overridepublic void visitHuman(Human human) {report.append("=== 人类健康检查报告 ===\n");report.append("姓名: ").append(human.getName()).append("\n");report.append("年龄: ").append(human.getAge()).append("岁\n");report.append("心率: ").append(human.getHeartRate()).append("bpm\n");report.append("体温: ").append(human.getBodyTemperature()).append("°C\n");String status = human.getHeartRate() > 100 ? "⚠️ 心率过高" : human.getBodyTemperature() > 37.5 ? "⚠️ 发烧" : "✅ 健康";report.append("状态: ").append(status).append("\n\n");}@Overridepublic void visitRobot(Robot robot) {report.append("=== 机器人诊断报告 ===\n");report.append("型号: ").append(robot.getModel()).append("\n");report.append("序列号: ").append(robot.getSerialNumber()).append("\n");report.append("电池电量: ").append(robot.getBatteryLevel()).append("%\n");report.append("运行时间: ").append(robot.getOperatingHours()).append("小时\n");String status = robot.getBatteryLevel() < 20 ? "⚠️ 电量不足" : robot.getOperatingHours() > 10000 ? "⚠️ 需要维护" : "✅ 正常";report.append("状态: ").append(status).append("\n\n");}@Overridepublic String getReport() {return report.toString();}
}// 维护访问者
public class MaintenanceVisitor implements Visitor {private StringBuilder report = new StringBuilder();private double totalCost = 0;@Overridepublic void visitHuman(Human human) {report.append("=== 人类保养建议 ===\n");report.append("姓名: ").append(human.getName()).append("\n");if (human.getAge() > 40) {report.append("建议: 年度体检\n");totalCost += 500;}if (human.getHeartRate() > 90) {report.append("建议: 心血管检查\n");totalCost += 300;}report.append("预估费用: ¥").append(totalCost).append("\n\n");}@Overridepublic void visitRobot(Robot robot) {report.append("=== 机器人维护方案 ===\n");report.append("型号: ").append(robot.getModel()).append("\n");if (robot.getBatteryLevel() < 30) {report.append("建议: 更换电池\n");totalCost += 800;}if (robot.getOperatingHours() > 8000) {report.append("建议: 全面检修\n");totalCost += 2000;}if (robot.getOperatingHours() > 10000) {report.append("建议: 关键部件更换\n");totalCost += 5000;}report.append("预估费用: ¥").append(totalCost).append("\n\n");}@Overridepublic String getReport() {return "总维护费用: ¥" + totalCost + "\n" + report.toString();}
}// 升级访问者
public class UpgradeVisitor implements Visitor {private StringBuilder report = new StringBuilder();@Overridepublic void visitHuman(Human human) {report.append("=== 人类能力提升建议 ===\n");report.append("姓名: ").append(human.getName()).append("\n");if (human.getAge() < 30) {report.append("建议: 专业技能培训\n");report.append("预期效果: 职业技能提升20%\n");} else {report.append("建议: 健康管理课程\n");report.append("预期效果: 寿命延长5年\n");}report.append("\n");}@Overridepublic void visitRobot(Robot robot) {report.append("=== 机器人升级方案 ===\n");report.append("型号: ").append(robot.getModel()).append("\n");if (robot.getOperatingHours() < 5000) {report.append("建议: 软件系统升级\n");report.append("预期效果: 性能提升15%\n");} else {report.append("建议: 硬件模块升级\n");report.append("预期效果: 使用寿命延长3年\n");}report.append("\n");}@Overridepublic String getReport() {return report.toString();}
}

3. 元素接口和具体元素类

// 元素接口
public interface Element {void accept(Visitor visitor);String getName();
}// 人类
public class Human implements Element {private String name;private int age;private double heartRate;private double bodyTemperature;public Human(String name, int age, double heartRate, double bodyTemperature) {this.name = name;this.age = age;this.heartRate = heartRate;this.bodyTemperature = bodyTemperature;}@Overridepublic void accept(Visitor visitor) {visitor.visitHuman(this);}@Overridepublic String getName() {return name;}// Getter方法public int getAge() { return age; }public double getHeartRate() { return heartRate; }public double getBodyTemperature() { return bodyTemperature; }
}// 机器人
public class Robot implements Element {private String model;private String serialNumber;private int batteryLevel;private int operatingHours;public Robot(String model, String serialNumber, int batteryLevel, int operatingHours) {this.model = model;this.serialNumber = serialNumber;this.batteryLevel = batteryLevel;this.operatingHours = operatingHours;}@Overridepublic void accept(Visitor visitor) {visitor.visitRobot(this);}@Overridepublic String getName() {return model + "-" + serialNumber;}// Getter方法public String getModel() { return model; }public String getSerialNumber() { return serialNumber; }public int getBatteryLevel() { return batteryLevel; }public int getOperatingHours() { return operatingHours; }
}

4. 对象结构类

// 对象结构
public class DiagnosticCenter {private List<Element> elements = new ArrayList<>();public void addElement(Element element) {elements.add(element);}public void performDiagnosis(Visitor visitor) {System.out.println("开始诊断检查...\n");for (Element element : elements) {element.accept(visitor);}System.out.println(visitor.getReport());System.out.println("诊断完成\n");}public void showAllElements() {System.out.println("=== 诊断中心成员 ===");for (Element element : elements) {System.out.println("- " + element.getName());}System.out.println();}
}

5. 客户端代码

public class VisitorPatternDemo {public static void main(String[] args) {System.out.println("=== 访问者模式演示 - 人类和机器人诊断系统 ===\n");// 创建诊断中心DiagnosticCenter center = new DiagnosticCenter();// 添加人类和机器人center.addElement(new Human("张三", 35, 85, 36.8));center.addElement(new Human("李四", 45, 95, 37.2));center.addElement(new Robot("T-800", "001", 65, 12000));center.addElement(new Robot("R2-D2", "002", 15, 3000));// 显示所有成员center.showAllElements();// 执行健康检查System.out.println("执行健康检查:");center.performDiagnosis(new HealthCheckVisitor());// 执行维护检查System.out.println("执行维护检查:");center.performDiagnosis(new MaintenanceVisitor());// 执行升级建议System.out.println("执行升级建议:");center.performDiagnosis(new UpgradeVisitor());System.out.println("=== 演示完成 ===");}
}

在Spring的应用

在Spring框架中,访问者模式的应用体现在:

  1. Bean定义访问BeanDefinitionVisitor用于访问和修改bean定义
  2. 注解处理AnnotationMetadataVisitor用于访问类的注解信息
  3. 资源访问ResourceVisitor用于处理资源文件访问逻辑
  4. 数据访问:JPA和Hibernate中的访问者模式用于实体检查和验证
  5. 表达式解析:Spring Expression Language (SpEL) 使用访问者模式解析表达式
  6. AOP处理:切面编程中的访问者模式用于方法拦截和处理

总结

访问者模式通过将操作与对象结构分离,使得可以在不修改现有类的情况下添加新的操作。它特别适用于需要对一个复杂对象结构中的多个元素执行不同操作的场景,如诊断系统、编译器设计、文档处理等。虽然会增加系统复杂性,但提供了很好的扩展性和灵活性。

http://www.sczhlp.com/news/115019/

相关文章:

  • 提供零基础网站建设教学网站开发技术交流
  • 做一个自己的免费网站吗网页设计架构
  • 网站搭建中单页面同一个域名网站做301
  • 黑龙江生产建设兵团网站网络管理系统的特点
  • 普通的订阅号怎么做微网站重庆做网站 熊掌号
  • 自己建网站的流程百度我的订单
  • 如何做网站效果图重庆建设工程信息网网
  • 好的建网站公司个人网站备案可以做博客吗
  • 贵州华瑞网站建设有限公司amh wordpress伪静态设置
  • 青岛做网站的公司j2ee只做网站
  • 网站开发飞沐wordpress上传图片x
  • 深圳网站开发外包哪家好营销方式
  • 怎么免费创建网站wordpress联系表单 数据库
  • 广西柳州网站建设电商网站有哪些功能
  • 印度喜欢用什么框架做外贸网站合肥瑶海区范围
  • 专业营销软件网站建设佛山网页开发
  • 如何知道别人的网站流量来自于哪里商贸公司起名字大全免费
  • 傻瓜式php网站开发工具取名字的网站 优帮云
  • 网站建设哪家go国内免费图片素材网站
  • 云服务器网站搭建长春网站制作都找源晟27
  • 泰国做企业网站怎么制作公司宣传图片
  • 来年做那个网站能致富网站一年费用
  • 怎样查询网站是否备案ftp中如何找到网站首页
  • 织梦小说网站模板下载百度推广登录平台app
  • 网站只收录主页网络事件营销
  • 泉州公司网站设计管理系统门户网站开发路线
  • 建站公司推广十堰最新新闻今天
  • 吉林市做网站的公司哪家好如何查网站外链
  • 上海网站建设咨学ui设计难不难
  • 莆田网站建设多少钱网站备案号怎么添加