访问者模式


文章目录

  • 访问者模式
  • 前言
  • 一、访问者模式(Visitor)
  • 二、角色
  • 三、应用场景
  • 四、代码实现
    • 1. 抽象元素
    • 2.具体元素
    • 3.定义提供给访问者的抽象方法
    • 4.CEO关注KPI
    • 5.结构化对象
    • 6.访问客户端
    • 7.代码输出
  • 总结
    • 优点:
    • 缺点:

前言

在生活中,针对同一件物品,因为观察角度不同,所得到的结果也有所不同,访问者以某一类的物品触发,详细实现了多角度多物品的观察结果,比如规则性物体,可以抽象出来连个元素,正方体和长方体。抽象访问者可以抽象出来观察的角度,例如正视图,左视图,俯视图,然后由具体访问者实现观察角度,子类与实际元素类数量相同,可以使不同的物体具有相同的观察操作,通过结构对象维护元素集合,提供方法接受访问者对元素进行操作。


一、访问者模式(Visitor)

可以将数据结构与数据操作分离,比如封装一些操作某种数据结构的算法,可以在不改变数据结构的前提下,定义元素的新操作。

二、角色

  1. 抽象访问者(IVisitor):接口或抽象类,定义了一个visit方法用于访问每个具体的元素,参数时具体对象。
  2. 具体访问者(Concret Visitor):实现对具体结构对象的元素的操作。
  3. 抽象元素(IElement):接口或抽象类,定义了一个接受访问者访问的方法accept(),表示所有元素类型都支持被访问者访问。
  4. 具体元素(Concrete Element): 接受访问者的具体实现。
  5. 结构对象(Object Structure):维护元素集合,并提供方法接受访问者对该集合所有元素进行操作。

三、应用场景

  • 数据结构稳定,数据结构操作经常变化的场景
  • 数据结构与数据操作分离的场景
  • 需要对不同数据类型(元素)进行操作,而不使用分支判断具体类型的场景。

四、代码实现

1. 抽象元素

代码如下(示例): 抽象被访问者,定义某类元素的抽象

     /// <summary>/// 抽象元素/// 抽象被访问者////// </summary>public interface IEmployee{public string Name { get; set; }public string Depament { get; set; }public int KPI { get; set; }void Accept(IKPIVisitor kPIVisitor);}

2.具体元素

代码如下(示例):被访问的元素以及被访问的方法

 /// <summary>/// 被访问的元素以及被访问的方法/// </summary>public class Dev : IEmployee{public Dev(string Name){this.Name = Name;this.Depament = "开发";this.KPI = new Random().Next(10);}public int KPI { get; set; }public string Name { get; set; }public string Depament { get; set; }public void Accept(IKPIVisitor kPIVisitor){kPIVisitor.KPIVisitor(this);}public int CodeRowCount(){var bugNumber = new Random().Next(100000);Console.WriteLine($"部门{this.Depament},{this.Name}写出{bugNumber}行代码");return bugNumber;}}/// <summary>/// 被访问的元素以及被访问的方法/// </summary>public class ProjectManager : IEmployee{public ProjectManager(string Name){this.Name = Name;this.Depament = "PM";this.KPI = new Random().Next(10);}public int KPI { get; set; }public string Name { get; set; }public string Depament { get; set; }public void Accept(IKPIVisitor kPIVisitor){kPIVisitor.KPIVisitor(this);}public int DomandaEffettiva(){var bugNumber = new Random().Next(10000);Console.WriteLine($"部门{this.Depament},{this.Name}提出{bugNumber}个有效需求");return bugNumber;}}/// <summary>/// 被访问的元素以及被访问的方法/// </summary>public class Tester : IEmployee{public Tester(string Name){this.Name = Name;this.Depament = "测试";this.KPI = new Random().Next(10);}public int KPI { get; set; }public string Name { get; set; }public string Depament { get; set; }public void Accept(IKPIVisitor kPIVisitor){kPIVisitor.KPIVisitor(this);}public int BugNumber(){var bugNumber = new Random().Next(10000);Console.WriteLine($"部门{this.Depament},{this.Name}测试出BUG{bugNumber}个");return bugNumber;}}

3.定义提供给访问者的抽象方法

代码如下(示例):所有具体访问者都继承自这个抽象,然后在继承者内进行内部实现,实现子类内部关注内容,比如,技术总监关注具体的工作内容,CEO关注任务的完成度

     /// <summary>/// 定义提供给访问者的抽象方法/// 所有具体访问者都继承自这个抽象,然后在继承者内进行内部实现,实现子类内部关注内容/// 比如,技术总监关注具体的工作内容,CEO关注任务的完成度/// </summary>public interface IKPIVisitor{/// <summary>/// 开发的KPI实现/// </summary>/// <param name="employee"></param>void KPIVisitor(Dev employee);/// <summary>/// 产品的KPI实现/// </summary>/// <param name="employee"></param>void KPIVisitor(ProjectManager employee);/// <summary>/// 测试的KPI实现/// </summary>/// <param name="employee"></param>void KPIVisitor(Tester employee);}

4.CEO关注KPI

代码如下(示例):

 /// <summary>/// CEO关注KPI/// </summary>public class CEOVisitor : IKPIVisitor{public void KPIVisitor(Dev employee){Console.WriteLine($"{employee.Depament}:{employee.Name},KPI为{employee.KPI}");}public void KPIVisitor(ProjectManager employee){Console.WriteLine($"{employee.Depament}:{employee.Name},KPI为{employee.KPI}");}public void KPIVisitor(Tester employee){Console.WriteLine($"{employee.Depament}:{employee.Name},KPI为{employee.KPI}");}}/// <summary>/// CTo关注的所有内容实现/// </summary>public class CTOVisitor : IKPIVisitor{/// <summary>/// CTO关注开发的代码行数/// </summary>/// <param name="employee"></param>public void KPIVisitor(Dev employee){Console.WriteLine($"{employee.Depament}:{employee.Name},代码行数为{employee.CodeRowCount()}");}/// <summary>/// CTO关注产品的有效需求/// </summary>/// <param name="employee"></param>public void KPIVisitor(ProjectManager employee){Console.WriteLine($"{employee.Depament}:{employee.Name},有效需求{employee.DomandaEffettiva()}");}/// <summary>/// CTO关注测试的BUG数/// </summary>/// <param name="employee"></param>/// <exception cref="NotImplementedException"></exception>public void KPIVisitor(Tester employee){Console.WriteLine($"{employee.Depament}:{employee.Name},BUG数{employee.BugNumber()}");}}

5.结构化对象

代码如下(示例):结构化对象

 /// <summary>/// 结构化对象/// </summary>public class BussingssReposrt{private List<IEmployee> employees = new List<IEmployee>();public BussingssReposrt(){employees.Add(new Dev("开发菜鸟"));employees.Add(new Dev("开发菜鸡"));employees.Add(new ProjectManager("产品菜鸟"));employees.Add(new ProjectManager("产品菜鸡"));employees.Add(new Tester("测试大牛"));}public void showReport(IKPIVisitor kPIVisitor){foreach (var item in employees){item.Accept(kPIVisitor);}}}

6.访问客户端

代码如下(示例):结构化对象

  public class EmployeeClient {public void clientMain() {BussingssReposrt bussingssReposrt = new BussingssReposrt();Console.WriteLine("----------------------------CEO------------------------------");bussingssReposrt.showReport(new CEOVisitor());Console.WriteLine("----------------------------CTO------------------------------");bussingssReposrt.showReport(new CTOVisitor());}}

7.代码输出

代码如下(示例):


----------------------------CEO------------------------------
开发:开发菜鸟,KPI为3
开发:开发菜鸡,KPI为7
PM:产品菜鸟,KPI为5
PM:产品菜鸡,KPI为0
测试:测试大牛,KPI为4
----------------------------CTO------------------------------
部门开发,开发菜鸟写出17530行代码
开发:开发菜鸟,代码行数为17530
部门开发,开发菜鸡写出75555行代码
开发:开发菜鸡,代码行数为75555
部门PM,产品菜鸟提出2673个有效需求
PM:产品菜鸟,有效需求2673
部门PM,产品菜鸡提出1719个有效需求
PM:产品菜鸡,有效需求1719
部门测试,测试大牛测试出BUG9341个
测试:测试大牛,BUG数9341

总结

相同的数据结构,观察角度不同,生成的报表内容不同。

优点:

  • 数据结构与数据操作解耦,使操作集合可以独立变化
  • 扩展访问者角色,实现对数据集群的不同操作,程序扩展性更高
  • 元素具体类型并非单一,访问者均可操作
  • 各角色职责分离,符合单一职责原则。

缺点:

  • 无法增加元素类型
  • 具体元素变更困难
  • 违背了依赖倒置原则,

设计模式-行为型-访问者模式相关推荐

  1. [设计模式-行为型]访问者模式(Vistor)

    一句话 表示一个作用于某对象结构中的各元素的操作.它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作. 概括 解析 情人节到了,要给每个MM送一束鲜花和一张卡片,可是每个MM送的花都要针对 ...

  2. 设计模式学习之访问者模式

    访问者模式,是行为型设计模式之一.访问者模式是一种将数据操作与数据结构分离的设计模式,它可以算是 23 中设计模式中最复杂的一个,但它的使用频率并不是很高,大多数情况下,你并不需要使用访问者模式,但是 ...

  3. 设计模式 - 行为型 - 模板模式学习

    现象: 设计模式 - 行为型 - 模板模式学习 介绍: 模板模式的设计思路,在抽象类中定义抽象方法的执行顺序, 并将抽象方法设定为只有子类实现,但不提供独立访问的方法 只能通过已经被安排好的定义方法去 ...

  4. 设计模式学习之访问者模式(Visitor,行为型模式)(21)

    参考:https://www.cnblogs.com/edisonchou/p/7247990.html 在患者就医时,医生会根据病情开具处方单,很多医院都会存在以下这个流程:划价人员拿到处方单之后根 ...

  5. 设计模式笔记(24)---访问者模式(行为型)

    Gof定义 表示一个作用于某对象结构中的各元素的操作.它可以在不改变各元素的类的前提下定义作用于这些元素的新的操作. 动机 在软件构建过程中,由于需求的改变,某些类层次结构中常常需要增加新的行为(方法 ...

  6. 设计模式--23、访问者模式

    访问者模式是一种较为复杂的行为型设计模式,它包含访问者和被访问元素两个主要组成部分,这些被访问的元素通常具有不同的类型,且不同的访问者可以对它们进行不同的访问操作.例如处方单中的各种药品信息就是被访问 ...

  7. 设计模式行为型-状态模式

    最近学习了设计模式行为型中的状态模式,这个模式的就完全体现出"多态"这种性质了,首先是它的解释:当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类. 为什么说状 ...

  8. C#设计模式系列:访问者模式(Visitor)

    1.访问者模式简介 1.1>.定义 作用于某个对象群中各个对象的操作,可以使在不改变对象本身的情况下,定义作用于对象的新操作. 1.2>.使用频率   低 2.访问者模式结构 2.1> ...

  9. 《研磨设计模式》chap25 访问者模式Visitor(3)联合组合模式+总结

    1. 联合组合模式 //抽象的组件对象,相当于访问者模式中的元素对象 public abstract class Component {//接受访问者的访问 public abstract void ...

最新文章

  1. Linux驱动框架之framebuffer驱动框架
  2. [云炬商业计划书阅读分享]无水洗车市场推广策划书
  3. MobileNet、GhostNet理解及测试
  4. 秒杀多线程第九篇 经典线程同步总结 关键段 事件 互斥量 信号量
  5. 为什么c语言要定义变量,C语言为什么要规定对所用到的变量要“先定义,后使用”...
  6. mysql 数据库表锁死_mysql 数据库表被锁住了_Mysql数据库表锁死如何处理?
  7. 哪些数据库是行存储?哪些是列存储?有什么区别?
  8. 吴恩达深度学习2.3笔记_Improving Deep Neural Networks_超参数调试 和 Batch Norm
  9. 《『若水新闻』客户端开发教程》——10.代码编写(2)
  10. FPGA中亚稳态相关问题及跨时钟域处理
  11. UCenter密码算法规则和生成方法
  12. 验票证明怎么打印_纳税人证明在哪里打印
  13. MongoDB官网下载和安装(ZIP安装)
  14. Deep Mind 团队论文Playing Atari with Deep Reinforcement Learning复现
  15. 命名转小驼峰大驼峰中划线
  16. turlebot3 ROS相关求助
  17. Hive面试题考点-整理
  18. android Camera 设置焦距
  19. C语言1.5e10什么意思,汽车排量1.5e是什么意思
  20. 基于Python的基金数据汇总分析

热门文章

  1. 最小二乘支持向量机(lssvm)回归预测(matlab)
  2. 巧解决阿里云虚拟主机免费版被DDOS攻击问题
  3. 【yolov3】如何使用摄像头进行目标检测——yolov3-pytorch摄像头检测教程
  4. python是一种语言吗-python是一种什么类型的语言
  5. 什么是Platform SDK?
  6. Echarts清空图表:There is a chart instance already initialized on the dom.
  7. 2018年android常用的框架介绍
  8. 程序与进程的区别和联系
  9. [安装fastfds中的nginx执行make命令报错]src/core/ngx_murmurhash.c:37:11: error
  10. 如何使用手机将图片改成JPG格式?教你一招解决