C# 设计模式(行为型模式):访问者模式

embedded/2025/1/7 21:38:53/

C# 设计模式(行为型模式):访问者模式

在复杂的系统中,我们可能需要对一组对象执行不同的操作,而这些操作往往会根据对象的类型有所不同。访问者模式(Visitor Pattern)是一种行为型设计模式,它可以帮助我们将数据结构与操作解耦,使得新增操作变得更加灵活。

访问者模式的定义

访问者模式是一种将操作与其作用的对象结构分离的设计模式。它通过为对象结构增加一个访问者(Visitor)对象,将需要对数据结构进行的操作从数据结构本身分离出来。

访问者模式的结构

访问者模式通常由以下几个部分组成:

  1. Visitor(访问者): 定义对元素进行访问的操作接口。
  2. ConcreteVisitor(具体访问者): 实现访问者接口,定义对每种具体元素的操作。
  3. Element(元素): 定义一个接受访问者的方法(Accept),允许访问者访问自身。
  4. ConcreteElement(具体元素): 实现接受操作,并将自身作为参数传递给访问者。
  5. ObjectStructure(对象结构): 管理元素的集合,并提供遍历元素的功能。

示例:公司员工的薪资计算

我们以计算不同类型员工的薪资为例:

  • 普通员工的薪资按基本工资计算。
  • 部门经理的薪资需要额外加上绩效奖金。

代码实现

using System;
using System.Collections.Generic;// 访问者接口
public interface IVisitor
{void Visit(Employee employee);void Visit(Manager manager);
}// 元素接口
public interface IElement
{void Accept(IVisitor visitor);
}// 普通员工类
public class Employee : IElement
{public string Name { get; set; }public double Salary { get; set; } // 基本工资public Employee(string name, double salary){Name = name;Salary = salary;}public void Accept(IVisitor visitor){visitor.Visit(this);}
}// 部门经理类
public class Manager : IElement
{public string Name { get; set; }public double Salary { get; set; } // 基本工资public double Bonus { get; set; } // 绩效奖金public Manager(string name, double salary, double bonus){Name = name;Salary = salary;Bonus = bonus;}public void Accept(IVisitor visitor){visitor.Visit(this);}
}// 具体访问者:薪资计算器
public class SalaryCalculator : IVisitor
{public void Visit(Employee employee){Console.WriteLine($"员工 {employee.Name} 的薪资是:{employee.Salary}");}public void Visit(Manager manager){Console.WriteLine($"经理 {manager.Name} 的薪资是:{manager.Salary + manager.Bonus}");}
}// 对象结构
public class Company
{private List<IElement> _elements = new List<IElement>();public void AddElement(IElement element){_elements.Add(element);}public void ShowSalaries(IVisitor visitor){foreach (var element in _elements){element.Accept(visitor);}}
}// 测试代码
class Program
{static void Main(string[] args){// 创建公司对象结构Company company = new Company();company.AddElement(new Employee("张三", 5000));company.AddElement(new Manager("李四", 8000, 2000));// 创建访问者SalaryCalculator calculator = new SalaryCalculator();// 计算薪资company.ShowSalaries(calculator);}
}

输出结果

员工 张三 的薪资是:5000
经理 李四 的薪资是:10000

访问者模式的优缺点

优点

  1. 符合单一职责原则: 将数据结构和操作解耦。
  2. 扩展性好: 增加新的访问者时,无需修改数据结构。
  3. 灵活性高: 可以在不修改元素类的前提下,为对象结构增加新的操作。

缺点

  1. 违反开闭原则: 如果需要修改元素类,则需要修改所有相关代码。
  2. 实现复杂: 对象结构和访问者之间的依赖关系较复杂。
  3. 双分派问题: 在访问者和元素之间引入了双分派机制,可能导致性能开销。

适用场景

  1. 对象结构稳定,但需要频繁增加新操作。
  2. 不同类型的对象需要执行不同的操作,并且这些操作易于变化。

总结

访问者模式将操作从对象结构中分离出来,通过访问者对对象进行扩展和操作,特别适用于对象结构稳定但操作多变的场景。在实际开发中,例如编译器中的抽象语法树遍历、报表生成等场景,都可以考虑使用访问者模式


http://www.ppmy.cn/embedded/151801.html

相关文章

MySQL低版本没有函数row_number() over的解决方案

最近在维护老项目时&#xff0c;需要对历史数据做分析取出分区数据中的第一条&#xff0c;无奈因为MySQL版本过低&#xff0c;无法使用函数row_number() over&#xff0c;苍了个天~ 不过这点小事怎么可能难倒我们这群考古专家呢&#xff0c;在此分享一下解决方案。 主要原因是问…

Sublime Text4 4189 安装激活【 2025年1月3日 亲测可用】

-----------------测试时间2025年1月3日------------------- 下载地址 官方网址&#xff1a;https://www.sublimetext.com 更新日志&#xff1a;https://www.sublimetext.com/download V4189 64位&#xff1a;https://www.sublimetext.com/download_thanks?targetwin-x64 ....…

C#Halcon跨窗口颜色识别

机器视觉是一门让计算机模拟人类视觉功能的学科。颜色识别在其中扮演着重要的角色&#xff0c;它旨在通过对图像中的颜色信息进行分析&#xff0c;从而识别出图像中的目标物体或者区域。例如&#xff0c;在水果分拣系统中&#xff0c;可以根据水果的颜色&#xff08;如苹果的红…

qt-C++笔记之动画框架(Qt Animation Framework)入门

qt-C笔记之动画框架(Qt Animation Framework)入门 code review! 在 Linux 平台上&#xff0c;使用 C 和 Qt 框架实现动画是一个非常好的选择。Qt 提供了强大的动画框架&#xff08;Qt Animation Framework&#xff09;&#xff0c;使得动画的实现变得简单高效。下面将介绍 Qt …

Git命令行的使用

目录 一、什么是Git 1、本地仓库 vs 远端仓库 本地仓库 远端仓库 2、.git vs .gitignore .git .gitignore 二、使用Git命令 1、安装git 2、git首次使用需要配置用户邮箱和用户名 3、上传目录/文件到远端仓库步骤 1&#xff09;创建放置文件的目录 2&#xff09;cd…

基于Python的考研学习系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏&#xff1a;…

php 多进程那点事,用 swoole 如何解决呢 ?

在 PHP 中&#xff0c;多进程的处理通常会遇到一些挑战&#xff0c;比如资源共享、进程间通信、性能优化等。Swoole 是一个高性能的协程和多进程框架&#xff0c;旨在为 PHP 提供异步、并发、协程等功能&#xff0c;解决了传统 PHP 环境中的多进程管理问题。通过使用 Swoole&am…

【记录】Angr|Angr 的 call_state 是怎么保证不同架构的函数的参数正常传递进去的?

文章目录 前言结论&#xff1a;遵循调用约定传参call_state 函数 api 声明基本说明必需参数可选参数返回值重要说明 call_state 的函数传参方式1. 函数参数传递概述必需参数&#xff1a;可选参数&#xff1a; 2. 如何传递参数2.1 参数类型转换2.2 寄存器和内存中的参数2.3 自动…