(17).访问者模式

访问者模式(Visitor Pattern)是一种行为型设计模式,它允许你在不修改对象结构的情况下,为对象结构中的元素添加新的操作。访问者模式将数据结构和数据操作分离,使得你可以灵活地添加新的操作而不需要改变现有的类。
在C#中实现访问者模式时,通常需要以下几个角色:
  1. Visitor: 定义一个接口或抽象类,表示对每个元素的操作。
  2. ConcreteVisitor: 实现Visitor接口,具体定义对每个元素的操作。
  3. Element: 定义一个接受访问者的接口,所有被访问的元素都需要实现这个接口。
  4. ConcreteElement: 具体的元素类,实现接受访问者的接口。
  5. 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

访问者模式的优点

  1. 扩展性:可以在不修改现有类的情况下,为对象结构添加新的操作。
  2. 单一职责原则:将数据结构和数据操作分离,符合单一职责原则。
  3. 复用性:访问者可以复用,不同的访问者可以对同一组对象进行不同的操作。

访问者模式的缺点

  1. 违反开闭原则:如果增加新的元素类,需要修改访问者接口和所有具体访问者类。
  2. 复杂性:对于简单的操作,使用访问者模式可能会显得过于复杂。

总结

访问者模式适用于以下场景:
  • 需要对一组对象进行多种不同的操作,且不想修改这些对象的类。
  • 需要在不改变对象结构的情况下,动态地为对象添加新的操作。
posted @ 2025-03-15 20:44  小码哥-风云  阅读(36)  评论(0)    收藏  举报