设计模式学习笔记-访问者模式
概述:
访问者模式(Visitor),表示作用于某对象结构中的各元素的操作。
它使你可以在不改变各元素的类的前提下定义作用于这些元素新的操作。
适用场合:
1.一个对象结构包含很多类对象,他们有不同的接口,而你想对这些对象实施一些依赖于其具体类的操作。
2.需要对一个对象中的对象进行很多不同的并且不相关的操作,而你想避免让这些操作‘污染’这些对象的类。
visitor使得你可以将相关的操作集中起来定义在一个类中。
当该对象结构被很多应用共享时,使用Visitor模式让每个应用包含需要用到的操作。
3.定义对象结构类很少改变,但经常需要在此结构上定义新的操作。
改变对象结构类需要重定义对所有访问者的接口,这可能需要很大的代价。
如果对象结构类经常改变,那么可能还是在这些类中定义这些操作较好。
类图:
代码示例:
1.访问者抽象类
/// <summary>
/// 为该对象结构中ConcreteElement的每一个类声明一个Visit操作
/// </summary>
abstract class Visitor
{
public abstract void VisitConcreteElementA(ConcreteElementA concreteElementA);
public abstract void VisitConcreteElementB(ConcreteElementB concreteElementB);
}
2.实现访问者类
/// <summary>
/// 具体访问者,实现Visitor的操作,每个操作实现算法的一部分,该算法乃是对应
/// 于结构中对象的类
/// </summary>
class ConcreteVisitor1:Visitor
{
public override void VisitConcreteElementA(ConcreteElementA concreteElementA)
{
Console.WriteLine("{0}被{1}访问",concreteElementA.GetType().Name,this.GetType().Name);
}
public override void VisitConcreteElementB(ConcreteElementB concreteElementB)
{
Console.WriteLine("{0}被{1}访问",concreteElementB.GetType().Name,this.GetType().Name);
}
}
class ConcreteVisitor2:Visitor
{
public override void VisitConcreteElementA(ConcreteElementA concreteElementA)
{
Console.WriteLine("{0}被{1}访问", concreteElementA.GetType().Name, this.GetType().Name);
}
public override void VisitConcreteElementB(ConcreteElementB concreteElementB)
{
Console.WriteLine("{0}被{1}访问", concreteElementB.GetType().Name, this.GetType().Name);
}
}
3. 定义Element,它以一个访问者为参数
/// <summary>
/// 定义一个Accept操作,它以一个访问者为参数
/// </summary>
abstract class Element
{
public abstract void Accept(Visitor visitor);
}
4.实现Accept操作
/// <summary>
/// 具体元素,实现Accept操作
/// </summary>
class ConcreteElementA:Element
{
/// <summary>
/// 充分利用双分派技术,实现处理与数据结构的分离
/// </summary>
/// <param name="visitor"></param>
public override void Accept(Visitor visitor)
{
visitor.VisitConcreteElementA(this);
}
/// <summary>
/// 其他的相关方法
/// </summary>
public void OperationA()
{
}
}
class ConcreteElementB:Element
{
public override void Accept(Visitor visitor)
{
visitor.VisitConcreteElementB(this);
}
public void OperationB() { }
}
5.定义一个高层接口
/// <summary>
/// 提供一个高层接口允许访问者访问它的元素
/// </summary>
class ObjectStructure
{
private IList<Element> elements = new List<Element>();
public void Attach(Element element)
{
elements.Add(element);
}
public void Dettach(Element element)
{
elements.Remove(element);
}
public void Accept(Visitor visitor)
{
foreach(Element e in elements)
{
e.Accept(visitor);
}
}
}
6.客户端调用
/// <summary>
/// 测试访问者模式
/// </summary>
static void TestVisitor()
{
ObjectStructure o = new ObjectStructure();
o.Attach(new ConcreteElementA());
o.Attach(new ConcreteElementB());
ConcreteVisitor1 v1 = new ConcreteVisitor1();
ConcreteVisitor2 v2 = new ConcreteVisitor2();
o.Accept(v1);
o.Accept(v2);
Console.Read();
}
小结:
访问者模式有点复杂,而且应用场合很少,具体应用需要将实际情况合理抽象,需要多种设计模式配合工作。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架