【从零入门23种设计模式24】行为型之访问者模式

【从零入门23种设计模式24】行为型之访问者模式

一、访问者模式核心定义

访问者模式是行为型设计模式的一种,核心目的是:

将数据结构与对数据的操作分离,使得操作可以独立于数据结构变化;定义一个作用于某对象结构中各元素的操作,而无需改变各元素的类。

简单来说:把对不同类型对象的操作(如计算、校验、导出)封装成独立的 “访问者” 类,数据对象接受访问者的访问并调用对应操作,实现 “数据不动,操作动”

核心解决的问题
  1. 解耦数据结构与操作:数据对象(如订单、商品、用户)的结构稳定,但对数据的操作(如统计、导出、校验)频繁变化时,无需修改数据类;
  2. 复用操作逻辑:同一套操作(如导出 Excel)可作用于不同类型的数据对象;
  3. 集中管理同类操作:所有数据对象的 “导出” 操作集中在ExportVisitor中,而非分散在各个数据类中;
  4. 支持多态操作:不同类型的数据对象对同一访问者会执行不同的操作(如订单导出、商品导出逻辑不同);
  5. 符合开闭原则:新增操作只需新增访问者类,无需修改数据对象类。
生活类比
  • 场景 1:商场巡检
    • 数据结构:商场中的不同元素(店铺、仓库、办公室);
    • 访问者:不同的巡检人员(安全巡检员、卫生巡检员、消防巡检员);
    • 核心:每个巡检人员(访问者)对不同场所(数据对象)执行不同的巡检操作,场所只需接受访问并配合巡检,无需修改自身逻辑。
  • 场景 2:财务审计
    • 数据结构:公司的不同资产(固定资产、流动资产、无形资产);
    • 访问者:审计人员(税务审计、财务审计、合规审计);
    • 核心:审计人员(访问者)对不同资产(数据对象)执行审计操作,资产类无需修改,新增审计类型只需新增访问者。
  • 场景 3:电商数据统计
    • 数据结构:订单、商品、用户;
    • 访问者:统计访问者(销售额统计、用户活跃度统计、商品销量统计);
    • 核心:统计访问者遍历所有数据对象,执行对应统计操作,新增统计维度只需新增访问者。
标准角色
角色职责类比(商场巡检场景)代码定位
抽象元素(Element)定义接受访问者的接口(accept(Visitor visitor)),所有数据对象实现该接口场所接口(Place):accept(Inspector visitor)接口 / 抽象类
具体元素(ConcreteElement)实现抽象元素接口,调用访问者的对应方法(如visitor.visitShop(this)店铺(Shop)、仓库(Warehouse)数据对象类
抽象访问者(Visitor)定义对所有具体元素的访问方法(visitShop(Shop shop)visitWarehouse(Warehouse warehouse)巡检员接口(Inspector):checkShop()checkWarehouse()接口 / 抽象类
具体访问者(ConcreteVisitor)实现抽象访问者接口,封装对不同元素的具体操作逻辑安全巡检员(SafetyInspector)、卫生巡检员(CleanlinessInspector)操作实现类
对象结构(ObjectStructure)管理元素集合,提供遍历元素的方法,供访问者遍历所有元素执行操作商场(Mall):管理所有场所,提供遍历方法集合管理类
核心 UML 类图

二、电商数据统计

以 “电商数据统计” 为例,实现访问者模式的核心逻辑 —— 数据对象(订单、商品、用户)结构稳定,统计操作(销售额、销量、活跃度)封装为访问者,新增统计维度只需新增访问者,无需修改数据类。
1. 步骤 1:定义抽象元素(数据对象接口)
/** * 抽象元素:电商数据对象接口(定义接受访问者的方法) */ public interface EcommerceElement { /** * 接受访问者访问 */ void accept(EcommerceVisitor visitor); } 
2. 步骤 2:实现具体元素(订单 / 商品 / 用户)
/** * 具体元素1:订单 */ public class OrderElement implements EcommerceElement { private String orderId; // 订单ID private double amount; // 订单金额 private int productCount; // 商品数量 public OrderElement(String orderId, double amount, int productCount) { this.orderId = orderId; this.amount = amount; this.productCount = productCount; } // 核心:接受访问者,调用访问者的订单访问方法 @Override public void accept(EcommerceVisitor visitor) { visitor.visitOrder(this); } // Getter public String getOrderId() { return orderId; } public double getAmount() { return amount; } public int getProductCount() { return productCount; } } /** * 具体元素2:商品 */ public class ProductElement implements EcommerceElement { private String productId; // 商品ID private String productName; // 商品名称 private int salesCount; // 销量 public ProductElement(String productId, String productName, int salesCount) { this.productId = productId; this.productName = productName; this.salesCount = salesCount; } @Override public void accept(EcommerceVisitor visitor) { visitor.visitProduct(this); } // Getter public String getProductId() { return productId; } public String getProductName() { return productName; } public int getSalesCount() { return salesCount; } } /** * 具体元素3:用户 */ public class UserElement implements Ecomm

Read more

《C/C+++ Boost 轻量级搜索引擎实战:架构流程、技术栈与工程落地指南——构造正/倒排索引(中篇)》

《C/C+++ Boost 轻量级搜索引擎实战:架构流程、技术栈与工程落地指南——构造正/倒排索引(中篇)》

前引:这是一个聚焦基础搜索引擎核心工作流的实操项目,基于 C/C++ 技术生态落地:从全网爬虫抓取网页资源,到服务器端完成 “去标签 - 数据清洗 - 索引构建” 的预处理,再通过 HTTP 服务接收客户端请求、检索索引并拼接结果页返回 —— 完整覆盖了轻量级搜索引擎的端到端逻辑。项目采用 C++11、STL、Boost 等核心技术栈,搭配 CentOS 7 云服务器 + GCC 编译环境(或 VS 系列开发工具)部署,既适配后端工程的性能需求,也能通过可选的前端技术(HTML5/JS 等)优化用户交互,是理解搜索引擎底层原理与 C++ 工程实践的典型案例 目录 【一】Jieba分词工具 【二】正/倒排索引结构设计

By Ne0inhk
深入理解 MySQL:索引、数据库设计、事务与视图

深入理解 MySQL:索引、数据库设计、事务与视图

在日常的后端开发中,MySQL 作为一款经典的关系型数据库,是我们数据存储和管理的核心工具。想要让 MySQL 发挥出最优性能,同时保证数据的完整性、一致性和安全性,就必须深入掌握索引、数据库设计、事务和视图这些核心知识点。本文将结合实战场景,详细拆解这四大核心模块的使用逻辑与最佳实践。 一、索引:提升查询效率的 “加速器” 索引是 MySQL 优化查询性能的关键手段,其本质是一种特殊的数据结构(如 B + 树),能够帮助数据库快速定位到目标数据,避免全表扫描带来的性能损耗。 1. 索引的核心类型 (1)普通索引 最基础的索引类型,无唯一性约束,仅用于加速查询。 * 创建方式: -- 直接创建 CREATE INDEX idx_username ON user (username); -- 修改表结构添加 ALTER TABLE user ADD

By Ne0inhk
2025版最详细WebStorm下载安装教程(详细图解)

2025版最详细WebStorm下载安装教程(详细图解)

目录 一、前言 二、WebStorm的下载安装 1、下载WebStorm 2、安装WebStorm 3、首次启动WebStorm 一、前言 前端一般就是用WebStorm或者是VSCode,Jetbrains家的ide一般都比较重,VSCode相对而言就轻快一点。主要还是看大家自己喜欢哪个就下哪个,我个人电脑内存是32G所以我一直用Jetbrains家的软件体验不错。本博客记录一下WebStorm的安装流程,大家自行参考 然后WebStorm从24年10月开始就是免费的了,所以不需要任何许可证直接下了就能用,并且也不需要像Java和Python那样配JDK和解释器,整体还是很简单的 二、WebStorm的下载安装 1、下载WebStorm 打开浏览器,访问JetBrains的官方网址,点击如下网址能直接跳转到WebStorm的下载页面: Download WebStorm: The JavaScript and TypeScript IDE by JetBrains 选择好自己的系统,然后直接点击Download即可 等待安装包下载完成,网速快

By Ne0inhk
前端国际化之i18n(VUE项目)

前端国际化之i18n(VUE项目)

解释与说明         i18n,全名是internationalization,称为国际化。         我理解的就四个字:语言转换。         让以其他语言作为母语的人能看懂你的前端中的文字。         我们常用的就是中文简体(zh_CN)与英文(美国)(en_US)的转换。         当然也可以增添中文繁体(zh_TW)等等你想要的其他语言。 缩写的由来 internationalization,首字母 i 和末字母 n 之间有 18 个字母,故缩写为 i18n 。 与之对应的是L10n,本地化,Localization。         最好在项目初期就计划使用国际化,这样相对后期使用会大大减少工作量。 项目使用 安装 1,在你的软件中打开控制台         我使用的是IDEA,其实前端更推荐使用VSCode。 2,进入前端的文件夹 cd web         我的前端的文件夹名称是web,相应变换成你自己命名的前端文件夹名称。 3,使用下载安装命令 npm

By Ne0inhk