(17).访问者模式
访问者模式(Visitor Pattern)是一种行为型设计模式,它允许你在不修改对象结构的情况下,为对象结构中的元素添加新的操作。访问者模式将数据结构和数据操作分离,使得你可以灵活地添加新的操作而不需要改变现有的类。
在C#中实现访问者模式时,通常需要以下几个角色:
- Visitor: 定义一个接口或抽象类,表示对每个元素的操作。
- ConcreteVisitor: 实现Visitor接口,具体定义对每个元素的操作。
- Element: 定义一个接受访问者的接口,所有被访问的元素都需要实现这个接口。
- ConcreteElement: 具体的元素类,实现接受访问者的接口。
- ObjectStructure: 包含元素的集合,并提供方法让访问者访问这些元素。
访问者模式的基本结构
1. Visitor 接口
public interface IVisitor
{
void Visit(ConcreteElementA elementA);
void Visit(ConcreteElementB elementB);
}
2. ConcreteVisitor 实现
public class ConcreteVisitor1 : IVisitor
{
public void Visit(ConcreteElementA elementA)
{
Console.WriteLine("ConcreteVisitor1 visiting ConcreteElementA");
}
public void Visit(ConcreteElementB elementB)
{
Console.WriteLine("ConcreteVisitor1 visiting ConcreteElementB");
}
}
public class ConcreteVisitor2 : IVisitor
{
public void Visit(ConcreteElementA elementA)
{
Console.WriteLine("ConcreteVisitor2 visiting ConcreteElementA");
}
public void Visit(ConcreteElementB elementB)
{
Console.WriteLine("ConcreteVisitor2 visiting ConcreteElementB");
}
}
3. Element 接口
public interface IElement
{
void Accept(IVisitor visitor);
}
4. ConcreteElement 实现
public class ConcreteElementA : IElement
{
public void Accept(IVisitor visitor)
{
visitor.Visit(this);
}
public void OperationA()
{
Console.WriteLine("ConcreteElementA operation.");
}
}
public class ConcreteElementB : IElement
{
public void Accept(IVisitor visitor)
{
visitor.Visit(this);
}
public void OperationB()
{
Console.WriteLine("ConcreteElementB operation.");
}
}
5. ObjectStructure 类
public class ObjectStructure
{
private List<IElement> elements = new List<IElement>();
public void Add(IElement element)
{
elements.Add(element);
}
public void Remove(IElement element)
{
elements.Remove(element);
}
public void Accept(IVisitor visitor)
{
foreach (var element in elements)
{
element.Accept(visitor);
}
}
}
示例代码
下面是一个完整的示例,展示了如何使用访问者模式。
using System;
using System.Collections.Generic;
// Visitor 接口
public interface IVisitor
{
void Visit(ConcreteElementA elementA);
void Visit(ConcreteElementB elementB);
}
// ConcreteVisitor1 实现
public class ConcreteVisitor1 : IVisitor
{
public void Visit(ConcreteElementA elementA)
{
Console.WriteLine("ConcreteVisitor1 visiting ConcreteElementA");
}
public void Visit(ConcreteElementB elementB)
{
Console.WriteLine("ConcreteVisitor1 visiting ConcreteElementB");
}
}
// ConcreteVisitor2 实现
public class ConcreteVisitor2 : IVisitor
{
public void Visit(ConcreteElementA elementA)
{
Console.WriteLine("ConcreteVisitor2 visiting ConcreteElementA");
}
public void Visit(ConcreteElementB elementB)
{
Console.WriteLine("ConcreteVisitor2 visiting ConcreteElementB");
}
}
// Element 接口
public interface IElement
{
void Accept(IVisitor visitor);
}
// ConcreteElementA 实现
public class ConcreteElementA : IElement
{
public void Accept(IVisitor visitor)
{
visitor.Visit(this);
}
public void OperationA()
{
Console.WriteLine("ConcreteElementA operation.");
}
}
// ConcreteElementB 实现
public class ConcreteElementB : IElement
{
public void Accept(IVisitor visitor)
{
visitor.Visit(this);
}
public void OperationB()
{
Console.WriteLine("ConcreteElementB operation.");
}
}
// ObjectStructure 类
public class ObjectStructure
{
private List<IElement> elements = new List<IElement>();
public void Add(IElement element)
{
elements.Add(element);
}
public void Remove(IElement element)
{
elements.Remove(element);
}
public void Accept(IVisitor visitor)
{
foreach (var element in elements)
{
element.Accept(visitor);
}
}
}
class Program
{
static void Main(string[] args)
{
// 创建对象结构
ObjectStructure objectStructure = new ObjectStructure();
objectStructure.Add(new ConcreteElementA());
objectStructure.Add(new ConcreteElementB());
// 创建访问者
IVisitor visitor1 = new ConcreteVisitor1();
IVisitor visitor2 = new ConcreteVisitor2();
// 使用访问者访问对象结构
Console.WriteLine("Visiting with ConcreteVisitor1:");
objectStructure.Accept(visitor1);
Console.WriteLine("\nVisiting with ConcreteVisitor2:");
objectStructure.Accept(visitor2);
}
}
输出结果
Visiting with ConcreteVisitor1:
ConcreteVisitor1 visiting ConcreteElementA
ConcreteVisitor1 visiting ConcreteElementB
Visiting with ConcreteVisitor2:
ConcreteVisitor2 visiting ConcreteElementA
ConcreteVisitor2 visiting ConcreteElementB
访问者模式的优点
- 扩展性:可以在不修改现有类的情况下,为对象结构添加新的操作。
- 单一职责原则:将数据结构和数据操作分离,符合单一职责原则。
- 复用性:访问者可以复用,不同的访问者可以对同一组对象进行不同的操作。
访问者模式的缺点
- 违反开闭原则:如果增加新的元素类,需要修改访问者接口和所有具体访问者类。
- 复杂性:对于简单的操作,使用访问者模式可能会显得过于复杂。
总结
访问者模式适用于以下场景:
- 需要对一组对象进行多种不同的操作,且不想修改这些对象的类。
- 需要在不改变对象结构的情况下,动态地为对象添加新的操作。

浙公网安备 33010602011771号