访问者模式(Visitor Pattern)
概念:
· 一种行为型设计模式;
· 将作用于某些对象结构中的操作封装成独立的访问者类,从而实现在不改变元素类的情况下,对元素进行新的操作;
UML结构:
+----------------+ | IVisitor | ← 访问者接口 +----------------+ | visit(ElementA)| | visit(ElementB)| +----------------+ ^ | +--------------------+ | ConcreteVisitor | ← 具体访问者,实现具体操作 +--------------------+ | visit(ElementA) | | visit(ElementB) | +--------------------+ +----------------+ | IElement | ← 元素接口 +----------------+ | accept(visitor)| +----------------+ ^ | +--------------------+ | ConcreteElementA | ← 具体元素 +--------------------+ | operationA() | | accept(visitor) | +--------------------+ +--------------------+ | ConcreteElementB | +--------------------+ | operationB() | | accept(visitor) | +--------------------+代码示例:
cs/// <summary> /// 产品接口类 /// </summary> public interface IProduct { void Accept(IVisitor visitor); } /// <summary> /// 访问者接口类 /// </summary> public interface IVisitor { void Visit(Electronics electronics); void Visit(Book book); void Visit(Food food); } /// <summary> /// 产品基类 /// </summary> public abstract class ProductBase { public float _TaxRate { get; set; } public float _Price { get; set; } public string _Description { get; set; } public float _Discount { get; set; } public ProductBase(float taxRate, float price, string description, float discount) { _TaxRate = taxRate; _Price = price; _Description = description; _Discount = discount; } public abstract void Accept(IVisitor visitor); } /// <summary> /// 具体产品1 /// </summary> public class Electronics : ProductBase, IProduct { public Electronics(float taxRate, float price, string description, float discount) : base(taxRate, price, description, discount) { } public override void Accept(IVisitor visitor) { visitor.Visit(this); } } /// <summary> /// 具体产品2 /// </summary> public class Book : ProductBase, IProduct { public Book(float taxRate, float price, string description, float discount) : base(taxRate, price, description, discount) { } public override void Accept(IVisitor visitor) { visitor.Visit(this); } } /// <summary> /// 具体产品3 /// </summary> public class Food : ProductBase, IProduct { public Food(float taxRate, float price, string description, float discount) : base(taxRate, price, description, discount) { } public override void Accept(IVisitor visitor) { visitor.Visit(this); } } /// <summary> /// 具体访问者1 /// </summary> public class CalculatePrice : IVisitor { public float TotalPrice { get; set; } = 0; public void Visit(Electronics electronics) { TotalPrice += electronics.Price * (1 + electronics.TaxRate); Console.WriteLine($"当前总价格为:{TotalPrice}"); } public void Visit(Book book) { TotalPrice += book.Price * (1 + book.TaxRate); Console.WriteLine($"当前总价格为:{TotalPrice}"); } public void Visit(Food food) { TotalPrice += food.Price * (1 + food.TaxRate); Console.WriteLine($"当前总价格为:{TotalPrice}"); } } /// <summary> /// 具体访问者2 /// </summary> public class GenerateDescription : IVisitor { public void Visit(Electronics electronics) { Console.WriteLine($"电子产品描述:{electronics._Description}"); } public void Visit(Book book) { Console.WriteLine($"书籍描述:{book._Description}"); } public void Visit(Food food) { Console.WriteLine($"食物描述:{food._Description}"); } } /// <summary> /// 具体访问者3 /// </summary> public class ApplyDiscount : IVisitor { public void Visit(Electronics electronics) { Console.WriteLine($"电子产品打折规则:{electronics._Discount}"); } public void Visit(Book book) { Console.WriteLine($"书籍打折规则:{book._Discount}"); } public void Visit(Food food) { Console.WriteLine($"食物打折规则:{food._Discount}"); } } public class Client { public static void Main() { ProductBase electronics = new Electronics(0.15f, 5000f, "Gaming Laptop", 0.1f); ProductBase book = new Book(0.05f, 80f, "Design Patterns", 0.2f); ProductBase food = new Food(0.1f, 20f, "Organic Apple", 0.05f); IVisitor calculatePrice = new CalculatePrice(); IVisitor generateDescription = new GenerateDescription(); IVisitor applyDiscount = new ApplyDiscount(); electronics.Accept(calculatePrice); electronics.Accept(generateDescription); electronics.Accept(applyDiscount); book.Accept(calculatePrice); book.Accept(generateDescription); book.Accept(applyDiscount); food.Accept(calculatePrice); food.Accept(generateDescription); food.Accept(applyDiscount); } }特点:
优点:· 符合单一职责原则;
· 易于扩展新的操作;
· 结构清晰:把元素和操作分离,逻辑职责明确;
缺点:· 扩展新的元素时,需要修改已有的访问者接口和已有的访问者类;
· 违反封装:访问者需要访问元素的内部数据,破坏了封装性;
· 增加系统的复杂度:将操作与元素拆分会导致类的增多;
适用场景:
· 对象结构稳定,元素个数相对固定,但是需要不断增加新操作;
· 对象结构中有很多不同类型的对象,并希望对这些对象实现不同的操作;
· 希望能把数据与操作逻辑分离;
· 希望通过向不同的对象传入相同的参数以实现与其对应的不同操作;
举例场景:
· 文档处理系统
元素:段落、图片、表格;
操作(访问者):导出HTML、拼写检查、统计信息;
【设计模式】访问者模式
大飞pkz2025-10-05 11:14
相关推荐
Chester_19996 小时前
CSP202203C.计算资源调度器EXI-小洲7 小时前
Java 操作 Word:字符串替换、图片插入、动态生成表格与API接口下载会周易的程序员7 小时前
给 PLC 写一个字节码虚拟机:STVM 虚拟机架构设计机器视觉知识推荐、就业指导7 小时前
为什么老说“纯 Qt 没啥就业市场”?telepan7 小时前
Qt 开发避坑与性能指南:如何优雅、安全地定义全局常量字符串?m0_695251498 小时前
Qt MaintenanceTool 使用国内镜像加速下载(超详细教程)大衛說9 小时前
《Python 从入门到精通》系列总览与学习路线可乐鸡翅yeah_10 小时前
hls.js 内存泄漏实战排查,直播 M3U8 长时间播放异常定位方案2601_9622035110 小时前
Java进阶07集合(续)郑州光合科技余经理11 小时前
本地生活服务系统:模块边界与结算字段怎么拆