访问者模式(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