最新要闻
- gta4热咖啡补丁下载_GTA4热咖啡
- 京口法院微电影把诈骗“演”给你看|世界热门
- 五一假期返程现特种兵式学习:小学生高铁小桌板上疯狂赶作业
- 1盒不到3元!特仑苏全脂/低脂牛奶大促:高蛋白 易吸收
- 世界简讯:AMD正式发布锐龙7040U APU:最先进4nm Zen4、15W超低功耗
- “非洲狮的好朋狗”?动物园回应圈养鸡羊狗:珍稀品种 非普通家禽|每日观点
- 320.37万人次,42.32亿元!海南“五一”旅游成绩单出炉 今日热文
- 全球热点评!众智科技:4月28日获融资买入89.58万元,占当日流入资金比例19.76%
- 特斯拉中国突然涨价 销售催“等等党”赶紧下单:早买车就是赚到
- 路人如何衡量汽车品牌营销费用高低?李想支了一招:看留言-天天速讯
- 止渴解腻夏日必备!果舒拉桂花酸梅晶好价:3盒券后29.9
- 男子在西湖捞手机日入约一万!官方回应:不是景区工作人员
- 热火老将乐福本赛季中期从骑士买断加盟
- 襄阳市市场监管局开展“你点襄检”专项执法行动_全球头条
- 中国影史第三!今年五一档电影总票房超15亿元
- 【天天播资讯】40系显卡3大优势!再买30系就冤了
广告
手机
iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?
警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案
- iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?
- 警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案
- 男子被关545天申国赔:获赔18万多 驳回精神抚慰金
- 3天内26名本土感染者,辽宁确诊人数已超安徽
- 广西柳州一男子因纠纷杀害三人后自首
- 洱海坠机4名机组人员被批准为烈士 数千干部群众悼念
家电
世界百事通!【访问者设计模式详解】C/Java/JS/Go/Python/TS不同语言实现
(资料图片)
简介
访问者模式(Visitor Pattern)是一种行为型模式。它封装一个访问者类,把各元素类的操作集合起来,目的是将数据结构与数据操作分离。在不改变原有元素类数据结构的前提下,改变了元素类的执行算法。
当某些较为稳定的东西(数据结构或算法),不想直接被改变但又想扩展功能,这时候适合用访问者模式。访问者模式的使用频率并不是很高,大多数情况下,你并不需要使用访问者模式,但是当你一旦需要使用它时,那你就是需要使用它了。
访问者模式有以下几个角色:
- 结构对象(ObjectStructure):结构对象角色,这是访问者模式的基础角色,包含多个类或者接口.
- 抽象元素(Element):定义一个接受访问操作accept(),以一个访问者Visitor作为参数。
- 具体元素(ConcreteElement):实现抽象节点的accept()方法和处理操作,调用Vistor的访问方法实现具体功能。
- 抽象访问者(Visitor):定义一个抽象接口,声明一个或多个访问操作,使得所有具体访问者都必须实现。
- 具体访问者(ConcreteVisitor):具体访问者角色,实现Visitor声明的接口。
作用
- 在数据基础类里面有一个方法接受访问者,将自身引用传入访问者,从而把不变的固定起来,把变化的开放出去。
- 通过隔离类中变化的东西,固定不变的东西,符合单一职责原则,同时具备较好的扩展性和灵活性。
实现步骤
- 先创建基本元素抽象类Element,确定accept()抽象方法。
- 分别创建几个具体的元素类,实现抽象元素的accept方法。
- 在创建Visitor抽象接口,定义visit方法,调用具体元素。
- 创建1个或多个Visitor类,继承抽象接口,客户将以此去访问具体元素。
- 再创建对象结构类,这是核心入口类,负责组合各种元素,以及传递访问者Visitor。
- 客户调用时先创建对象结构类,再指定访问者类,通过访问这类调用具体元素类
UML
Java代码
结构对象
// ObjectStructure.java 结构对象(ObjectStructure)public class ObjectStructure { // 可以想象为一台电脑,聚合了各种设备元素 private String name = "Computer Structure"; private List elements = new ArrayList(); // 结构对象初始化聚合了其他元素 public ObjectStructure() { addElement(new ConcreteElementA()); addElement(new ConcreteElementB()); } public void addElement(Element element) { elements.add(element); } // 传入访问者分发给其他元素 public void accept(Visitor visitor) { System.out .println("ObjectStructure::accept() [visitor.class = " + visitor.getClass().getSimpleName() + " visitor.name = " + visitor.getName() + "]"); for (Element element : elements) { element.accept(visitor); } } public String getName() { return this.name; }}
抽象访问者类
// Visitor.java 访问者Visitor抽象接口,定义不同的visit方法public interface Visitor { public void visit(ConcreteElementA concreteElementA); public void visit(ConcreteElementB concreteElementB); public String getName();}
具体访问者
// ConcreteVisitorA.java 具体访问者Apublic class ConcreteVisitorA implements Visitor { // 假如由不同厂商是程序的访问者 private String name = "Google Visitor"; @Override public void visit(ConcreteElementA concreteElementA) { System.out.println( "ConcreteVisitorA::visit() [Element.class = " + concreteElementA.getClass().getSimpleName() + " Element.name = " + concreteElementA.getName() + "]"); concreteElementA.operate(); } @Override public void visit(ConcreteElementB concreteElementB) { System.out.println("ConcreteVisitorA::visit() [Element.class = " + concreteElementB.getClass().getSimpleName() + " Element.name = " + concreteElementB.getName() + "]"); concreteElementB.operate(); } public String getName() { return this.name; }}
// ConcreteVisitorB.java 具体访问者Bpublic class ConcreteVisitorB implements Visitor { // 假如由不同厂商是程序的访问者 private String name = "Apple Visitor"; @Override public void visit(ConcreteElementA concreteElementA) { System.out.println( "ConcreteVisitorB::visit() [Element.class = " + concreteElementA.getClass().getSimpleName() + " Element.name = " + concreteElementA.getName() + "]"); concreteElementA.operate(); } @Override public void visit(ConcreteElementB concreteElementB) { System.out.println( "ConcreteVisitorB::visit() [Element.class = " + concreteElementB.getClass().getSimpleName() + " Element.name = " + concreteElementB.getName() + "]"); concreteElementB.operate(); } public String getName() { return this.name; }}
抽象元素类
// Element.java 抽象元素(Element),定义accept方法,传入抽象访问者abstract class Element { public abstract void accept(Visitor visitor);}
具体元素实现类
// ConcreteElementA.java 具体的元素实现者Apublic class ConcreteElementA extends Element { // 可以设想为显示器 private String name = "Monitor Element"; @Override public void accept(Visitor visitor) { System.out .println( "ConcreteElementA::accept() [visitor.class = " + visitor.getClass().getSimpleName() + " visitor.name = " + visitor.getName() + "]"); visitor.visit(this); } public void operate() { System.out.println("ConcreteElementA::operate() [" + this.getName() + "]"); } public String getName() { return this.name; }}
// ConcreteElementB.java 具体的元素实现者Bpublic class ConcreteElementB extends Element { private String name = "Keyboard Element"; @Override public void accept(Visitor visitor) { System.out.println( "ConcreteElementB::accept() [visitor.class = " + visitor.getClass().getSimpleName() + " visitor.name = " + visitor.getName() + "]"); visitor.visit(this); } public void operate() { System.out.println("ConcreteElementB::operate() [" + this.getName() + "]"); } public String getName() { return this.name; }}
测试调用
/** * 访问者模式是当客户需要访问具体各元素Element时,先建立一个访问者Visitor作为媒介 * 客户基于对象结构ObjectStructure,调用accept(),接受传入的访问者 * 对象结构向其他元素负责分发访问者,元素对象接受之后会将自己回传给访问者,从而访问者可以访问具体元素 */ ObjectStructure structure = new ObjectStructure(); // 接受访问者A,把访问者传递给具体元素 structure.accept(new ConcreteVisitorA()); System.out.println("===="); // 接受访问者B,把访问者传递给具体元素 structure.accept(new ConcreteVisitorB());
Go代码
结构对象
// ObjectStructure.go 结构对象(ObjectStructure)type ObjectStructure struct { name string elements []Element}func (o *ObjectStructure) AddElement(e Element) { o.elements = append(o.elements, e)}// 传入访问者分发给其他元素func (o *ObjectStructure) Accept(v Visitor) { fmt.Println( "ObjectStructure::Accept() [Visitor.name = " + v.GetName() + "]") // 通知全部元素成员接受访问者 for i := 0; i < len(o.elements); i++ { o.elements[i].Accept(v) } // for _, ele := range o.elements { // ele.Accept(v) // }}func (o *ObjectStructure) GetName() string { o.name = "Computer Structure" return o.name}// 结构对象的初始化函数func (o *ObjectStructure) Init() { // 可以想象为一台电脑,聚合了各种设备元素 fmt.Println("ObjectStructure::Init() ", o.GetName()) // 定义一个对象数组,长度可选 o.elements = make([]Element, 0, 100) // 结构对象初始化聚合了其他元素 o.AddElement(&ConcreteElementA{}) o.AddElement(&ConcreteElementB{})}
抽象访问者类
// Visitor.go 访问者Visitor抽象接口,定义不同的visit方法type Visitor interface { VisitA(e *ConcreteElementA) VisitB(e *ConcreteElementB) GetName() string}
具体访问者
// ConcreteVisitorA.go 具体访问者Atype ConcreteVisitorA struct { name string}func (v *ConcreteVisitorA) GetName() string { v.name = "Google Visitor(struct=ConcreteVisitorA)" return v.name}func (v *ConcreteVisitorA) VisitA(e *ConcreteElementA) { fmt.Println( "ConcreteVisitorA::VisitA() [Element.name = " + e.GetName() + "]") e.Operate()}func (v *ConcreteVisitorA) VisitB(e *ConcreteElementB) { fmt.Println( "ConcreteVisitorA::VisitB() [Element.name = " + e.GetName() + "]") e.Operate()}
// ConcreteVisitorB.go 具体访问者Btype ConcreteVisitorB struct { name string}func (v *ConcreteVisitorB) GetName() string { v.name = "Apple Visitor(struct=ConcreteVisitorB)" return v.name}func (v *ConcreteVisitorB) VisitB(e *ConcreteElementB) { fmt.Println( "ConcreteVisitorB::VisitB() [Element.name = " + e.GetName() + "]") e.Operate()}func (v *ConcreteVisitorB) VisitA(e *ConcreteElementA) { fmt.Println( "ConcreteVisitorB::VisitA() [Element.name = " + e.GetName() + "]") e.Operate()}
抽象元素类
// Element.go 抽象元素(Element),定义accept方法,传入抽象访问者// go无抽象类,用interface替代type Element interface { Accept(v Visitor) Operate() GetName() string}
具体元素实现类
// ConcreteElementA.go 具体的元素实现者Atype ConcreteElementA struct { name string}func (c *ConcreteElementA) GetName() string { c.name = `Monitor Element(struct=ConcreteElementA)` return c.name}func (e *ConcreteElementA) Accept(v Visitor) { fmt.Println( "ConcreteElementA::Accept() [Visitor.name = " + v.GetName() + "]") v.VisitA(e)}func (e *ConcreteElementA) Operate() { fmt.Println("ConcreteElementA::Operate() [" + e.GetName() + "]")}
// ConcreteElementB.go 具体的元素实现者Btype ConcreteElementB struct { name string}func (c *ConcreteElementB) GetName() string { c.name = "Keyboard Element(struct=ConcreteElementB)" return c.name}func (e *ConcreteElementB) Accept(v Visitor) { fmt.Println( "ConcreteElementB::Accept() [Visitor.name = " + v.GetName() + "]") v.VisitB(e)}func (e *ConcreteElementB) Operate() { fmt.Println("ConcreteElementB::Operate() [" + e.GetName() + "]")}
测试调用
func main() { fmt.Println("test start:") /** * 访问者模式是当客户需要访问具体各元素Element时,先建立一个访问者Visitor作为媒介 * 客户基于对象结构ObjectStructure,调用Accept(),接受传入的访问者 * 对象结构向其他元素负责分发访问者,元素对象接受之后会将自己回传给访问者,从而访问者可以访问具体元素 */ structure := src.ObjectStructure{} structure.Init() // 接受访问者A,把访问者传递给具体元素 structure.Accept(&src.ConcreteVisitorA{}) fmt.Println("====") // 接受访问者B,把访问者传递给具体元素 structure.Accept(&src.ConcreteVisitorB{})}
更多语言版本
不同语言设计模式源码:https://github.com/microwind/design-pattern
关键词:
-
世界百事通!【访问者设计模式详解】C/Java/JS/Go/Python/TS不同语言实现
简介访问者模式(VisitorPattern)是一种行为型模式。它封装一个访问者类,把各元素类的操作集合起来,目的
来源: -
THE PLANETS MERCURY -环境变量的设置提权以及SETENV的理解
主机发现sudonmap-sT--min-rate10000-p-192 168 28 32-oAnmapscan portssudonmap-sT-sC-sV-O-p22,8080192 168 28 3-oAnmapscan detailsudonmap
来源: -
嵌入式测试手册——基于NXP iMX6ULL开发板(2)
基于测试板卡:创龙科技TLIMX6U-EVM是一款基于NXPi MX6ULL的ARMCortex-A7高性能低功耗处理器设计的评估板,
来源: 世界百事通!【访问者设计模式详解】C/Java/JS/Go/Python/TS不同语言实现
THE PLANETS MERCURY -环境变量的设置提权以及SETENV的理解
嵌入式测试手册——基于NXP iMX6ULL开发板(2)
gta4热咖啡补丁下载_GTA4热咖啡
京口法院微电影把诈骗“演”给你看|世界热门
五一假期返程现特种兵式学习:小学生高铁小桌板上疯狂赶作业
1盒不到3元!特仑苏全脂/低脂牛奶大促:高蛋白 易吸收
世界简讯:AMD正式发布锐龙7040U APU:最先进4nm Zen4、15W超低功耗
“非洲狮的好朋狗”?动物园回应圈养鸡羊狗:珍稀品种 非普通家禽|每日观点
320.37万人次,42.32亿元!海南“五一”旅游成绩单出炉 今日热文
观热点:第1章 大数据概述
世界热点评!内网穿透
工控机中部署Ubuntu 22.04 系统
【财经分析】贝泰妮高增长不再 股价跌去六成后能否再出发?
全球热点评!众智科技:4月28日获融资买入89.58万元,占当日流入资金比例19.76%
特斯拉中国突然涨价 销售催“等等党”赶紧下单:早买车就是赚到
路人如何衡量汽车品牌营销费用高低?李想支了一招:看留言-天天速讯
止渴解腻夏日必备!果舒拉桂花酸梅晶好价:3盒券后29.9
男子在西湖捞手机日入约一万!官方回应:不是景区工作人员
热火老将乐福本赛季中期从骑士买断加盟
襄阳市市场监管局开展“你点襄检”专项执法行动_全球头条
【国际大宗商品早报】经济衰退前景打压国际油价大幅下挫4% 美麦涨超5% 当前关注
中国影史第三!今年五一档电影总票房超15亿元
【天天播资讯】40系显卡3大优势!再买30系就冤了
世界热议:喂到嘴边的肥肉!新势力无奈破产:富士康喜提造车工厂一座
阿里云:亏了13年刚赚钱 为啥被逼着五折大促销?
世界热资讯!916万人次假期逛郑州 尽享“文化味”“烟火气”
通过Python进行MySQL表信息统计
互联网鬼城!AI专属社交平台爆火:人类只能看不能说_全球最新
小米13 Ultra白色16GB+1 TB版今日首发:7299元
成交单价突破42万元 比亚迪:腾势D9连续4个月30万元以上新能源MPV第一
中远海发(02866.HK):5月3日南向资金减持98.5万股
芍药坦荡荡
云原生底座之上,这些企业领跑行业的秘密
二、高级语言语法描述
降价9万后雪铁龙C6销量暴涨!总经理:价格战对品牌有伤害
环球今日报丨李想怒怼车评媒体人:不投放你 就是因为你太爱煽风点火
骁龙8+平板只要2399!小米是懂人性弱点的-天天热讯
全网千万人学鼻子转牙签 详细教程在此:你学废了吗? 前沿热点
实时焦点:必胜韩国语园地原声韩剧在线观看_必胜韩国语园地
斩赤红之瞳结局谁活着_斩赤红之瞳结局
快消息!时隔7年季后赛再拿两双 两次重伤打不垮辽宁铁人
动态物体追踪 每日简讯
一季度苹果手机均价6800元 iPhone 14 Pro最畅销|全球即时看
上海漫展惊现“女菩萨”:还真有人顶礼膜拜-全球热头条
ASP.NET Core MVC 从入门到精通之HttpContext
24 操作系统的网络架构
AMD RX 7000全家倾巢出动 卡皇现世!苏姿丰:敬请期待
热心大哥高铁怒斥熊孩子家长获喝彩:掌声响起-世界最新
各地陆续迎来假期返程高峰
热推荐:汽油价格还要再大降?国际油价已跌超5%
全球今头条!徐州市人力和社会资源保障局网站_徐州市人力资源和社会保障网
最新:马斯克的星舰首飞:到底是成功了?还是失败了?
五一返程高峰遇强降雨 多地堵上加堵:局部140毫米大暴雨-热消息
天文专家回应哈尔滨现不明飞行物:可能是卫星残骸 没必要恐慌 每日资讯
KubeVela 稳定性及可扩展性评估_环球微动态
随机造数据的技巧总结
dotnetfx35无法安装_dotnetfx35
游客手机掉西湖被要1500元打捞费 景区:简单打捞不收费-全球观察
员工朋友圈未发广告被罚1万且开除:法院判赔5万 当前短讯
印度捷行航空申请破产 原因想不到:普惠发动机故障太多-视点
环球聚焦:appuploader 入门使用
环球快看点丨1、etcd基础介绍
【实变函数】01 - 更合理的积分
每日信息:关于如何使用pandas将不同的数据写入到同一个Excel的不同Sheet表中
【世界新视野】1159 Structure of a Binary Tree + 根据前序和中序构建二叉树+ 层序遍历模板复习
【e公司观察】原料涨价 锂电行业为何振奋不已?|当前看点
四川自贡一餐厅吃饭收15元空调费 店家:相当于雅间费-全球今头条
各主要高速公路、国省道干线交通总体安全顺畅 最新消息
热讯:写几行代码,了解响应式原理
第139篇:JS数组常用方法(map(),reduce(),foreach())
83.赋值运算符
IMF:中国将成为今年亚太地区经济增长关键驱动因素
有钱人为何在意电动车电费?李想用超级富豪朋友习惯解释原因-全球讯息
环球速看:格科微: 格科微有限公司关于公司实际控制人、董事长、首席执行官提议公司回购股份的公告
【2023 · CANN训练营第一季】昇腾AI入门Pytorch
世界微动态丨23 网络数据在内核中流转
ZooKeeper 避坑指南: ZooKeeper 3.6.4 版本 BUG 导致的数据不一致问题
5月3日全国铁路迎来返程客流高峰 预计发送旅客1935万人次 世界独家
上海妍秀国际医疗美容诊所医生以及擅长项目推荐
报道:上半年最后一个假 端午节放3天:假期后需连上6天班
《街霸6》新角色韩蛛俐介绍片:疯美人脚法了得-全球观天下
Bash—source命令&export命令&bashrc文件
最新快讯!三星宣布多款旧设备停止更新支持
清仓特价 森马板鞋/运动鞋39元起、T恤29元起-要闻速递
今日快讯:又一个小米6钉子户消失 米粉给妈妈换小米13 雷军点赞
22 URL到网卡:网络数据流动
“广州市十佳科普使者”出炉|全球观察
五一余额不足 最后一天返程现场排长队 网友:凌晨出门照堵不误
“插队婆孙”被做成恶搞表情包:如此“网暴”是否合适?
【全球聚看点】OpenAI API keys 的申请和测试小结
母子争吵儿子走丢 机场民警15分钟帮找到孩子|播资讯
【世界速看料】最便宜的16GB显存显卡出现了!AMD、NVIDIA统统靠边站
焦点报道:苹果、谷歌起草追踪设备行业规范:打击滥用定位功能
当前短讯!实惨!男子拍演唱会:激光导致手机摄像头直接报废
Realme 11 Pro+ 5G 曝光 在5月10日发布
66元的的钟薛高在东北只要3.8元一根!商家回应
开眼!丰田为混动车申请“手动挡”专利:只为保留驾驶乐趣 环球热推荐
游客停车31小时被收640元:明码标价 但已退还
Blazor学习之旅系列总结目录