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

设计模式(021)行为型之访问者模式

        访问者模式是一种行为型设计模式,它可以在不修改现有代码结构的情况下,为复杂的对象结构添加新的操作。该模式将数据结构和数据操作进行分离,使得数据结构可以独立于操作进行变化,同时也可以在不改变操作的前提下增加新的操作。
在访问者模式中,主要有以下几个角色:
① 访问者(Visitor):定义了对每个元素对象访问时所要执行的操作,可以通过多态实现针对不同元素的不同操作。
② 具体访问者(ConcreteVisitor):实现了访问者定义的接口,完成对元素对象的具体操作。
③ 元素(Element):定义了一个 `accept` 方法,用于接受访问者的访问。
④ 具体元素(ConcreteElement):实现了元素定义的接口,通常会在 `accept` 方法中调用访问者的方法。
⑤ 对象结构(ObjectStructure):包含一个元素的集合,通常提供一个方法让访问者遍历所有元素。
访问者模式适用于对象结构比较稳定,但经常需要在此对象结构上定义新的操作的情况,或者有复杂的对象结构需要一些独立的操作的情况。

1、场景设计

实现场景:对象结构中定义A、B两个元素,访问者对它们进行访问。

2、C++实现

`Visitor` 是抽象访问者类,`ConcreteVisitor` 是具体访问者类,`Element` 是抽象元素类,`ConcreteElementA` 和 `ConcreteElementB` 是具体元素类。`ObjectStructure` 是对象结构类,包含了一个元素的集合,可以接受访问者的访问。在 `main` 函数中,我们创建了一个具体的访问者和一个对象结构,然后向对象结构中添加了两个具体元素,最后让访问者访问对象结构。 

#include <iostream>
#include <vector>// 前置声明,防止循环引用
class ConcreteElementB;// 抽象访问者类
class Visitor {public:virtual void visit(ConcreteElementB* element) = 0;
};// 具体访问者类
class ConcreteVisitor : public Visitor {public:void visit(ConcreteElementB* element) override {std::cout << "ConcreteVisitor is visiting ConcreteElementB" << std::endl;}
};// 抽象元素类
class Element {public:virtual void accept(Visitor* visitor) = 0;
};// 具体元素类A
class ConcreteElementA : public Element {public:void accept(Visitor* visitor) override {std::cout << "ConcreteElementA is accepting visitor" << std::endl;}
};// 具体元素类B
class ConcreteElementB : public Element {public:void accept(Visitor* visitor) override {visitor->visit(this);}
};// 对象结构类
class ObjectStructure {private:std::vector<Element*> elements;public:void addElement(Element* element) {elements.push_back(element);}void accept(Visitor* visitor) {for (Element* element : elements) {element->accept(visitor);}}
};int main() {ConcreteVisitor visitor;ObjectStructure objectStructure;ConcreteElementA elementA;ConcreteElementB elementB;objectStructure.addElement(&elementA);objectStructure.addElement(&elementB);objectStructure.accept(&visitor);return 0;
}

3、Java实现

`Visitor` 是抽象访问者类,`ConcreteVisitor` 是具体访问者类,`Element` 是抽象元素类,`ConcreteElementA` 和 `ConcreteElementB` 是具体元素类。`ObjectStructure` 是对象结构类,包含了一个元素的集合,可以接受访问者的访问。在 `main` 方法中,我们创建了一个具体的访问者和一个对象结构,向对象结构中添加了两个具体元素,并让访问者访问对象结构。 

package behavioralpattern.visitor;import java.util.ArrayList;
import java.util.List;// 抽象访问者类
interface Visitor {void visit(ConcreteElementB element);
}// 具体访问者类
class ConcreteVisitor implements Visitor {@Overridepublic void visit(ConcreteElementB element) {System.out.println("ConcreteVisitor is visiting ConcreteElementB");}
}// 抽象元素类
interface Element {void accept(Visitor visitor);
}// 具体元素类A
class ConcreteElementA implements Element {@Overridepublic void accept(Visitor visitor) {System.out.println("ConcreteElementA is accepting visitor");}
}// 具体元素类B
class ConcreteElementB implements Element {@Overridepublic void accept(Visitor visitor) {visitor.visit(this);}
}// 对象结构类
class ObjectStructure {private List<Element> elements = new ArrayList<>();public void addElement(Element element) {elements.add(element);}public void accept(Visitor visitor) {for (Element element : elements) {element.accept(visitor);}}
}public class VisitorDemo {public static void main(String[] args) {ConcreteVisitor visitor = new ConcreteVisitor();ObjectStructure objectStructure = new ObjectStructure();ConcreteElementA elementA = new ConcreteElementA();ConcreteElementB elementB = new ConcreteElementB();objectStructure.addElement(elementA);objectStructure.addElement(elementB);objectStructure.accept(visitor);}
}

相关文章:

设计模式(021)行为型之访问者模式

访问者模式是一种行为型设计模式&#xff0c;它可以在不修改现有代码结构的情况下&#xff0c;为复杂的对象结构添加新的操作。该模式将数据结构和数据操作进行分离&#xff0c;使得数据结构可以独立于操作进行变化&#xff0c;同时也可以在不改变操作的前提下增加新的操作。 在…...

Linux中磁盘的分区,格式化,挂载和文件系统的修复

一.分区工具 1.分区工具介绍 fdisk 2t及以下分区 推荐 (分完区不保存不生效&#xff0c;有反悔的可能) gdisk 全支持 推荐 parted 全支持 不推荐 ( 即时生效&#xff0c;分完立即生效) 2.fdisk 分区,查看磁盘 格式:fdisk -l [磁盘设备] fdisk -l 查看…...

Android retrofit

目录 一.简介 二.基本使用 三.注解 四.转换器 五.适配器 六.文件上传与下载 一.简介 A type-safe HTTP client for Android and Java。封装了OkHttp&#xff0c;也是由Square公司贡献的一个处理网络请求的开源项目。 square/retrofit: A type-safe HTTP client for Andr…...

【C++风云录】五款 C++ 库的探索与应用:物联网、嵌入式与数据处理

提升你的C技能&#xff1a;五个关键库的使用与指南 前言 在今天的数字化世界里&#xff0c;C 作为一种强大且快速的编程语言&#xff0c;在各类复杂系统和应用的开发中扮演着重要角色。然而&#xff0c;单凭语言本身的能力&#xff0c;我们往往无法实现所有的功能需求&#x…...

Qt_30道常见面试题及答案

1. 简述 Qt 是什么&#xff1f; 答&#xff1a;Qt 是一个跨平台的应用程序开发框架&#xff0c;它提供了一系列的工具和库&#xff0c;用于开发图形用户界面&#xff08;GUI&#xff09;应用程序。 2. Qt 有哪些主要模块&#xff1f; 答&#xff1a;Qt 的主要模块包括 Qt Co…...

【vue】v-model 双向数据绑定

:value&#xff1a;单向数据绑定v-model&#xff1a;双向数据绑定 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0">…...

C#创建磁性窗体的方法:创建特殊窗体

目录 一、磁性窗体 二、磁性窗体的实现方法 (1)无标题窗体的移动 (2)Left属性 (3)Top属性 二、设计一个磁性窗体的实例 &#xff08;1&#xff09;资源管理器Resources.Designer.cs设计 &#xff08;2&#xff09;公共类Frm_Play.cs &#xff08;3&#xff09;主窗体 …...

Gateway 基本配置指南:构建高效的网络接入网关

简介&#xff1a; Gateway 是一个常用的网络接入网关&#xff0c;它可以帮助组织实现安全、可靠和高性能的网络连接。本文将介绍 Gateway 的基本配置&#xff0c;帮助读者了解如何正确配置和部署一个高效的 Gateway 网关。 1.网络拓扑规划&#xff1a; 在配置 Gateway 前&#…...

自定义类型: 结构体 (详解)

本文索引 一. 结构体类型的声明1. 结构体的声明和初始化2. 结构体的特殊声明3. 结构体的自引用 二. 结构体内存对齐1. 对齐规则2. 为啥存在对齐?3. 修改默认对齐值 三. 结构体传参四. 结构体实现位段1. 什么是位段?2. 位段的内存分配3. 位段的应用4. 位段的注意事项 ​ 前言:…...

设计模式(23):访问者模式

定义 表示一个作用于某对象结构中的各元素的操作&#xff0c;它使我们可以在不改变元素的类的前提下定义作用与这些元素的新操作。 模式动机 对于存储在一个集合中的对象&#xff0c;他们可能具有不同的类型(即使有一个公共的接口)&#xff0c;对于该集合中的对象&#xff0…...

【C++】类和对象③(类的默认成员函数:拷贝构造函数 | 赋值运算符重载)

&#x1f525;个人主页&#xff1a;Forcible Bug Maker &#x1f525;专栏&#xff1a;C 目录 前言 拷贝构造函数 概念 拷贝构造函数的特性及用法 赋值运算符重载 运算符重载 赋值运算符重载 结语 前言 本篇主要内容&#xff1a;类的6个默认成员函数中的拷贝构造函数…...

掀起区块链开发狂潮!Scaffold-eth带你一键打造震撼DApp

文章目录 前言一、Scaffold-eth是什么&#xff1f;二、安装和配置1.准备工作2.安装3.配置开发环境 三、进阶使用1.放入自己的合约2.部署运行 总结 前言 前面的文章传送&#x1f6aa;&#xff1a;hardhat入门 与 hardhat进阶 在之前的文章中&#xff0c;我们已经探讨了使用Har…...

【Qt 学习笔记】Qt常用控件 | 按钮类控件Check Box的使用及说明

博客主页&#xff1a;Duck Bro 博客主页系列专栏&#xff1a;Qt 专栏关注博主&#xff0c;后期持续更新系列文章如果有错误感谢请大家批评指出&#xff0c;及时修改感谢大家点赞&#x1f44d;收藏⭐评论✍ Qt常用控件 | 按钮类控件Check Box的使用及说明 文章编号&#xff1a;…...

android gradle 配置远程仓库

build.gradle buildscript { ext.kotlin_version "1.6.0" // 使用适合你项目的Kotlin版本 repositories { maven { url http://maven.aliyun.com/nexus/content/groups/public/ } maven { url http://maven.aliyun.com/nexus/content/repos…...

第十二章 OpenGL ES 基础-色温、色调、亮度、对比度、饱和度、高光

第十二章 OpenGL ES 基础-色温、色调、亮度、对比度、饱和度、高光 第一章 OpenGL ES 基础-屏幕、纹理、顶点坐标 第二章 OpenGL ES 基础-GLSL语法简单总结 第三章 OpenGL ES 基础-GLSL渲染纹理 第四章 OpenGL ES 基础-位移、缩放、旋转原理 第五章 OpenGL ES 基础-透视投影…...

力扣经典150题解析之二十八:盛最多水的容器

目录 力扣经典150题解析之二十八&#xff1a;盛最多水的容器1. 介绍2. 问题描述3. 示例4. 解题思路5. 算法实现6. 复杂度分析7. 测试与验证测试用例设计测试结果分析 8. 总结9. 参考文献感谢阅读 力扣经典150题解析之二十八&#xff1a;盛最多水的容器 1. 介绍 在这篇文章中&…...

Rockchip Android13 Vold(二):Framework层

目录 前言 1、接收VolumeInfo状态 2、通知VolumeInfo状态变化 3、创建StorageVolume...

Oracle数据库故障类别及日常运维规划策略

一、故障类别 1、语句故障 单个数据库操作失败&#xff08;select、insert、update或delete&#xff09;&#xff0c;如&#xff1a; 在表中输入无效的数据&#xff0c;解决方法&#xff1a;可与用户合作来验证并更正数据&#xff1b;执行操作&#xff0c;但权限不足&#x…...

电商技术揭秘九:搜索引擎中的SEO数据分析与效果评估

相关系列文章 电商技术揭秘一&#xff1a;电商架构设计与核心技术 电商技术揭秘二&#xff1a;电商平台推荐系统的实现与优化 电商技术揭秘三&#xff1a;电商平台的支付与结算系统 电商技术揭秘四&#xff1a;电商平台的物流管理系统 电商技术揭秘五&#xff1a;电商平台的个性…...

多线程传参以及线程的优缺点

进程是资源分配的基本单位 线程是调度的基本单位 笼统来说&#xff0c;线程有以下优点&#xff1a; 创建一个新线程的代价要比创建一个新进程小得多 与进程之间的切换相比&#xff0c;线程之间的切换需要操作系统做的工作要少很多 线程占用的资源要比进程少很多 能充分利用多…...

变量 varablie 声明- Rust 变量 let mut 声明与 C/C++ 变量声明对比分析

一、变量声明设计&#xff1a;let 与 mut 的哲学解析 Rust 采用 let 声明变量并通过 mut 显式标记可变性&#xff0c;这种设计体现了语言的核心哲学。以下是深度解析&#xff1a; 1.1 设计理念剖析 安全优先原则&#xff1a;默认不可变强制开发者明确声明意图 let x 5; …...

eNSP-Cloud(实现本地电脑与eNSP内设备之间通信)

说明&#xff1a; 想象一下&#xff0c;你正在用eNSP搭建一个虚拟的网络世界&#xff0c;里面有虚拟的路由器、交换机、电脑&#xff08;PC&#xff09;等等。这些设备都在你的电脑里面“运行”&#xff0c;它们之间可以互相通信&#xff0c;就像一个封闭的小王国。 但是&#…...

简易版抽奖活动的设计技术方案

1.前言 本技术方案旨在设计一套完整且可靠的抽奖活动逻辑,确保抽奖活动能够公平、公正、公开地进行,同时满足高并发访问、数据安全存储与高效处理等需求,为用户提供流畅的抽奖体验,助力业务顺利开展。本方案将涵盖抽奖活动的整体架构设计、核心流程逻辑、关键功能实现以及…...

逻辑回归:给不确定性划界的分类大师

想象你是一名医生。面对患者的检查报告&#xff08;肿瘤大小、血液指标&#xff09;&#xff0c;你需要做出一个**决定性判断**&#xff1a;恶性还是良性&#xff1f;这种“非黑即白”的抉择&#xff0c;正是**逻辑回归&#xff08;Logistic Regression&#xff09;** 的战场&a…...

8k长序列建模,蛋白质语言模型Prot42仅利用目标蛋白序列即可生成高亲和力结合剂

蛋白质结合剂&#xff08;如抗体、抑制肽&#xff09;在疾病诊断、成像分析及靶向药物递送等关键场景中发挥着不可替代的作用。传统上&#xff0c;高特异性蛋白质结合剂的开发高度依赖噬菌体展示、定向进化等实验技术&#xff0c;但这类方法普遍面临资源消耗巨大、研发周期冗长…...

使用 SymPy 进行向量和矩阵的高级操作

在科学计算和工程领域&#xff0c;向量和矩阵操作是解决问题的核心技能之一。Python 的 SymPy 库提供了强大的符号计算功能&#xff0c;能够高效地处理向量和矩阵的各种操作。本文将深入探讨如何使用 SymPy 进行向量和矩阵的创建、合并以及维度拓展等操作&#xff0c;并通过具体…...

C++使用 new 来创建动态数组

问题&#xff1a; 不能使用变量定义数组大小 原因&#xff1a; 这是因为数组在内存中是连续存储的&#xff0c;编译器需要在编译阶段就确定数组的大小&#xff0c;以便正确地分配内存空间。如果允许使用变量来定义数组的大小&#xff0c;那么编译器就无法在编译时确定数组的大…...

技术栈RabbitMq的介绍和使用

目录 1. 什么是消息队列&#xff1f;2. 消息队列的优点3. RabbitMQ 消息队列概述4. RabbitMQ 安装5. Exchange 四种类型5.1 direct 精准匹配5.2 fanout 广播5.3 topic 正则匹配 6. RabbitMQ 队列模式6.1 简单队列模式6.2 工作队列模式6.3 发布/订阅模式6.4 路由模式6.5 主题模式…...

人工智能(大型语言模型 LLMs)对不同学科的影响以及由此产生的新学习方式

今天是关于AI如何在教学中增强学生的学习体验&#xff0c;我把重要信息标红了。人文学科的价值被低估了 ⬇️ 转型与必要性 人工智能正在深刻地改变教育&#xff0c;这并非炒作&#xff0c;而是已经发生的巨大变革。教育机构和教育者不能忽视它&#xff0c;试图简单地禁止学生使…...

nnUNet V2修改网络——暴力替换网络为UNet++

更换前,要用nnUNet V2跑通所用数据集,证明nnUNet V2、数据集、运行环境等没有问题 阅读nnU-Net V2 的 U-Net结构,初步了解要修改的网络,知己知彼,修改起来才能游刃有余。 U-Net存在两个局限,一是网络的最佳深度因应用场景而异,这取决于任务的难度和可用于训练的标注数…...