cola架构:cola源码中访问者模式应用浅析
目录
1.访问者模式简介
2.cola访问者模式应用
2.1 cola被访问者类图
2.2 cola访问者类图
我们知道,如果一个对象结构包含很多类型的对象,希望对这些对象实施一些依赖其具体类型的操作,但又避免让这些操作“污染”这些对象的类,也不希望在增加新操作时修改这些类,那么可以使用访问者设计模式;它使得我们可以将相关的访问操作集中起来定义在访问者类中,将对象本身与对象的访问操作分离。
在cola框架中,针对状态机(StateMachine)和状态(State)就应用了访问者模式,下面进行具体分析;
附:
cola状态机源码解析见上篇文章:cola架构:有限状态机(FSM)源码分析
1.访问者模式简介
访问者(Visitor)模式:将作用于某种数据结构中的各元素的操作分离出来封装成独立的类,使其在不改变数据结构的前提下可以添加作用于这些元素的新的操作,为数据结构中的每个元素提供多种访问方式。
访问者模式包含的类/接口如下:
抽象访问者(Visitor):定义一个访问具体元素的接口,为每个具体元素类对应一个访问操作 visit() ,该操作中的参数类型标识了被访问的具体元素。
具体访问者(ConcreteVisitor):实现抽象访问者角色中声明的各个访问操作,确定访问者访问一个元素时该做什么。
抽象元素(Element):声明一个包含接受操作 accept() 的接口,被接受的访问者对象作为 accept() 方法的参数。
具体元素(ConcreteElement):实现抽象元素角色提供的 accept() 操作,其方法体通常都是 visitor.visit(this) ,另外具体元素中可能还包含本身业务逻辑的相关操作
对象结构(Object Structure):是一个包含元素角色的容器,提供让访问者对象遍历容器中的所有元素的方法,通常由 List、Set、Map 等聚合类实现。
相关类图及引用结构如下:

2.cola访问者模式应用
2.1 cola被访问者类图
cola被访问者类图如下,包含被访问者State和StateMachine:

Visitable接口定义了accept接口,接受Visitor参数对象:
public interface Visitable {String accept(final Visitor visitor);
}
StateImpl实现accept接口如下:
public class StateImpl<S,E,C> implements State<S,E,C> {@Overridepublic String accept(Visitor visitor) {String entry = visitor.visitOnEntry(this);String exit = visitor.visitOnExit(this);return entry + exit;}
}
StateMachineImpl实现accept接口如下:
public class StateMachineImpl<S, E, C> implements StateMachine<S, E, C> {@Overridepublic String accept(Visitor visitor) {StringBuilder sb = new StringBuilder();sb.append(visitor.visitOnEntry(this));for (State state : stateMap.values()) {sb.append(state.accept(visitor));}sb.append(visitor.visitOnExit(this));return sb.toString();}
}
实现逻辑里,通过简单调用访问者类的visit方法完成对被访问者的访问。
2.2 cola访问者类图
cola访问者包含PlantUMLVisitor和SysOutVisitor,类图如下:

Visitor接口约定了分别针对State和StateMachine的visit接口方法:
/*** Visitor** @author Frank Zhang* @date 2020-02-08 8:41 PM*/
public interface Visitor {char LF = '\n';/*** @param visitable the element to be visited.* @return*/String visitOnEntry(StateMachine<?, ?, ?> visitable);/*** @param visitable the element to be visited.* @return*/String visitOnExit(StateMachine<?, ?, ?> visitable);/*** @param visitable the element to be visited.* @return*/String visitOnEntry(State<?, ?, ?> visitable);/*** @param visitable the element to be visited.* @return*/String visitOnExit(State<?, ?, ?> visitable);
}
- PlantUMLVisitor实现了针对State和StateMachine的plantuml方式的输出格式;
- SysOutVisitor实现了对State和StateMachine简单日志输出;
/*** PlantUMLVisitor** @author Frank Zhang* @date 2020-02-09 7:47 PM*/
public class PlantUMLVisitor implements Visitor {/*** Since the state machine is stateless, there is no initial state.** You have to add "[*] -> initialState" to mark it as a state machine diagram.* otherwise it will be recognized as a sequence diagram.** @param visitable the element to be visited.* @return*/@Overridepublic String visitOnEntry(StateMachine<?, ?, ?> visitable) {return "@startuml" + LF;}@Overridepublic String visitOnExit(StateMachine<?, ?, ?> visitable) {return "@enduml";}@Overridepublic String visitOnEntry(State<?, ?, ?> state) {StringBuilder sb = new StringBuilder();for(Transition transition: state.getAllTransitions()){sb.append(transition.getSource().getId()).append(" --> ").append(transition.getTarget().getId()).append(" : ").append(transition.getEvent()).append(LF);}return sb.toString();}@Overridepublic String visitOnExit(State<?, ?, ?> state) {return "";}
}
/*** SysOutVisitor** @author Frank Zhang* @date 2020-02-08 8:48 PM*/
public class SysOutVisitor implements Visitor {@Overridepublic String visitOnEntry(StateMachine<?, ?, ?> stateMachine) {String entry = "-----StateMachine:"+stateMachine.getMachineId()+"-------";System.out.println(entry);return entry;}@Overridepublic String visitOnExit(StateMachine<?, ?, ?> stateMachine) {String exit = "------------------------";System.out.println(exit);return exit;}@Overridepublic String visitOnEntry(State<?, ?, ?> state) {StringBuilder sb = new StringBuilder();String stateStr = "State:"+state.getId();sb.append(stateStr).append(LF);System.out.println(stateStr);for(Transition transition: state.getAllTransitions()){String transitionStr = " Transition:"+transition;sb.append(transitionStr).append(LF);System.out.println(transitionStr);}return sb.toString();}@Overridepublic String visitOnExit(State<?, ?, ?> visitable) {return "";}
}
至此,应用访问者模式,实现了将被访问类和访问操作进行逻辑隔离、解耦。
相关文章:
cola架构:cola源码中访问者模式应用浅析
目录 1.访问者模式简介 2.cola访问者模式应用 2.1 cola被访问者类图 2.2 cola访问者类图 我们知道,如果一个对象结构包含很多类型的对象,希望对这些对象实施一些依赖其具体类型的操作,但又避免让这些操作“污染”这些对象的类,…...
Openssl数据安全传输平台015:OCCI的使用方法+在项目中的设计与实现
文章目录 1 OCCI使用1.1 初始化 - Environment 类1.2 连接数据库 - Connection 类1.3 执行SQL 2 OCCI在项目中的使用2.1 OCCI单独封装为一个类文件OCCIOP2.2 在ServerOP中作为私有成员2.3 ServerOP::ServerOP(string json)中实例化进行使用2.4 秘钥协商过程中进行读写操作 1 OC…...
ardupilot开发 --- CAN BUS、DroneCAN 、UAVCAN 篇
1. CAN BUS、DroneCAN 、UAVCAN 区别 UAVCAN是一种轻量级协议,旨在通过CAN BUS 在航空航天和机器人应用中实现可靠通信。 UAVCAN网络是分散的对等网络,其中每个对等体(节点)具有唯一的数字标识符 - 节点ID,并且仅需要…...
京东平台数据分析:2023年9月京东空气净化器行业品牌销售排行榜
鲸参谋监测的京东平台9月份空气净化器市场销售数据已出炉! 9月份,空气净化器的销售同比上年增长。根据鲸参谋平台的数据显示,今年9月,京东平台空气净化器的销量将近15万,同比增长约1%;销售额将近2亿元&…...
vue使日历组件点击时间渲染到时间输入框
首先,你需要在 Vue 中创建一个日历组件,该组件应该能够显示一个月的日历并允许用户选择日期。然后,当用户点击一个日期时,你需要将所选日期的值传递给父组件。最后,你可以在父组件中创建一个时间输入框,当用…...
TensorFlow学习:使用官方模型和自己的训练数据进行图片分类
前言 教程来源:清华大佬重讲机器视觉!TensorFlowOpencv:深度学习机器视觉图像处理实战教程,物体检测/缺陷检测/图像识别 注: 这个教程与官网教程有些区别,教程里的api比较旧,核心思想是没有变…...
MATLAB算法实战应用案例精讲-【图像处理】相机标定
目录 知识储备 距离算法和相似度计算方法 1、常见的距离算法 2、常见的相似度(系...
python画气泡标尺图
目录 渐变气泡图彩色气泡图 在进行实验结果分析的时候,气泡标尺图能非常清晰对不同的结果进行多维度的比较,特别是在深度学习模型大小和精度进行比较的时候非常合适使用,以下是几个例子。 渐变气泡图 import seaborn as sns import matplotl…...
Java并发编程指南:如何正确使用信号量和线程池熔断机制
前言: 在分布式系统中,选择合适的熔断机制是保护系统免受故障影响的关键。本文将介绍使用信号量和线程池两种常见的熔断机制,并提供Java和Spring Cloud Alibaba框架下的示例代码,帮助您深入理解和应用。 1. 信号量熔断机制 信号…...
大彩串口屏读写文件问题
分区 本文使用的是大彩串口屏M系列的: 串口屏内部有三个分区,分别为A、B、C三个区: A区:系统区,存储组态工程文件 B区:数据区,存储配置信息,记录数据、历史曲线等 C区:备…...
php之 角色的权限管理(RBAC)详解
RBAC(Role-based access control)是一种常见的权限管理模型,通过将用户分配至特定的角色,以及为角色分配访问权限,实现了权限管理的目的。以下是关于RBAC的详细解释: 角色:RBAC模型的核心是角色…...
asp.net乡村旅游管理系统VS开发sqlserver数据库web结构c#编程Microsoft Visual Studio
一、源码特点 asp.net乡村旅游管理系统是一套完善的web设计管理系统系统,系统具有完整的源代码和数据库,系统主要采用B/S模式开发。开发环境为vs2010,数据库为sqlserver2008,使用c# 语言开发 asp.net乡村旅游管理系统 二、…...
【linux】文件系统+软硬连接+动静态库
文件系统软硬连接动静态库 1.理解文件系统1.1磁盘的物理结构1.2磁盘的存储结构1.3磁盘的逻辑结构1.4文件系统 2.软硬链接2.1什么是软硬链接2.2软硬链接的作用 3.动静态库3.1什么是库3.1静态库和静态链接3.2动态库和动态链接3.2.1通过环境变量找到动态库路径3.2.2把动态库拷贝到…...
力扣每日一题73:矩阵置零
题目描述: 给定一个 m x n 的矩阵,如果一个元素为 0 ,则将其所在行和列的所有元素都设为 0 。请使用 原地 算法。 示例 1: 输入:matrix [[1,1,1],[1,0,1],[1,1,1]] 输出:[[1,0,1],[0,0,0],[1,0,1]]示例 2…...
vscode C++项目相对路径的问题
如图所示的项目目录结构 如果要在main.cpp里用相对路径保存一个txt文件 std::ofstream file("./tree_model/my_file.txt");if (file.is_open()) {file << "This is a sample text.\n";file.close();std::cout << "File saved in the mode…...
视频转换器WinX HD Video Converter mac中文特点介绍
WinX HD Video Converter mac是一款功能强大的视频转换器,它可以将各种不同格式的视频文件转换为其他视频格式,以便用户在各种设备上进行播放。WinX HD Video Converter是一个功能强大、易于使用的视频转换器,适用于各种类型的用户࿰…...
数据隐私保护的方法有哪些?
数据隐私保护的方法有哪些? 安企神U盘管理系统下载使用 互联网时代的到来,给我们的生活带来极大的方便,但也给我们保护隐私数据带来巨大的挑战,数据隐私保护是确保个人或企业数据和敏感信息不被未经授权的访问或滥用的关键问题。…...
【Linux】解决缓存锁问题:无法获得锁 /var/lib/dpkg/lock-frontend
今天在运行apt-get update更新软件包后,突然发现安装新的软件出现了这个报错:正在等待缓存锁:无法获得锁 /var/lib/dpkg/lock-frontend。锁正由进程 1855(unattended-upgr)持有。如图。 这个错误通常是由于其他进程正在…...
嵌入式软件开发工程师应该关注芯片数据手册中的哪些信息
1. 芯片的架构和处理器类型:了解芯片的架构和处理器类型可以帮助开发人员选择合适的开发工具和编程语言。 2. 芯片的时钟频率和电源要求:了解芯片的时钟频率和电源要求可以帮助开发人员设计合适的电路和电源系统。 3. 芯片的存储器类型和容量ÿ…...
基于数字电路交通灯信号灯控制系统设计-单片机设计
**单片机设计介绍,1617基于数字电路交通灯信号灯控制系统设计(仿真电路,论文报告 文章目录 一 概要二、功能设计设计思路 三、 软件设计原理图 五、 程序文档 六、 文章目录 一 概要 交通灯控制系统在城市交通控制中发挥着重要的作用…...
【kafka】Golang实现分布式Masscan任务调度系统
要求: 输出两个程序,一个命令行程序(命令行参数用flag)和一个服务端程序。 命令行程序支持通过命令行参数配置下发IP或IP段、端口、扫描带宽,然后将消息推送到kafka里面。 服务端程序: 从kafka消费者接收…...
反向工程与模型迁移:打造未来商品详情API的可持续创新体系
在电商行业蓬勃发展的当下,商品详情API作为连接电商平台与开发者、商家及用户的关键纽带,其重要性日益凸显。传统商品详情API主要聚焦于商品基本信息(如名称、价格、库存等)的获取与展示,已难以满足市场对个性化、智能…...
Xshell远程连接Kali(默认 | 私钥)Note版
前言:xshell远程连接,私钥连接和常规默认连接 任务一 开启ssh服务 service ssh status //查看ssh服务状态 service ssh start //开启ssh服务 update-rc.d ssh enable //开启自启动ssh服务 任务二 修改配置文件 vi /etc/ssh/ssh_config //第一…...
YSYX学习记录(八)
C语言,练习0: 先创建一个文件夹,我用的是物理机: 安装build-essential 练习1: 我注释掉了 #include <stdio.h> 出现下面错误 在你的文本编辑器中打开ex1文件,随机修改或删除一部分,之后…...
Frozen-Flask :将 Flask 应用“冻结”为静态文件
Frozen-Flask 是一个用于将 Flask 应用“冻结”为静态文件的 Python 扩展。它的核心用途是:将一个 Flask Web 应用生成成纯静态 HTML 文件,从而可以部署到静态网站托管服务上,如 GitHub Pages、Netlify 或任何支持静态文件的网站服务器。 &am…...
srs linux
下载编译运行 git clone https:///ossrs/srs.git ./configure --h265on make 编译完成后即可启动SRS # 启动 ./objs/srs -c conf/srs.conf # 查看日志 tail -n 30 -f ./objs/srs.log 开放端口 默认RTMP接收推流端口是1935,SRS管理页面端口是8080,可…...
spring:实例工厂方法获取bean
spring处理使用静态工厂方法获取bean实例,也可以通过实例工厂方法获取bean实例。 实例工厂方法步骤如下: 定义实例工厂类(Java代码),定义实例工厂(xml),定义调用实例工厂ÿ…...
#Uniapp篇:chrome调试unapp适配
chrome调试设备----使用Android模拟机开发调试移动端页面 Chrome://inspect/#devices MuMu模拟器Edge浏览器:Android原生APP嵌入的H5页面元素定位 chrome://inspect/#devices uniapp单位适配 根路径下 postcss.config.js 需要装这些插件 “postcss”: “^8.5.…...
Redis:现代应用开发的高效内存数据存储利器
一、Redis的起源与发展 Redis最初由意大利程序员Salvatore Sanfilippo在2009年开发,其初衷是为了满足他自己的一个项目需求,即需要一个高性能的键值存储系统来解决传统数据库在高并发场景下的性能瓶颈。随着项目的开源,Redis凭借其简单易用、…...
MacOS下Homebrew国内镜像加速指南(2025最新国内镜像加速)
macos brew国内镜像加速方法 brew install 加速formula.jws.json下载慢加速 🍺 最新版brew安装慢到怀疑人生?别怕,教你轻松起飞! 最近Homebrew更新至最新版,每次执行 brew 命令时都会自动从官方地址 https://formulae.…...
