为什么访问者模式通常只用于树?

Why is the visitor pattern typically used only for trees?

我最近成为访问者设计模式的粉丝(研究 lambda 表达式解析在 C# 中的工作原理的副作用),并开始在我自己的代码中频繁使用它。

然而,我注意到的一点是,当在 articles/tutorials 中讨论此模式时,用例是 几乎总是 trees/graphs。

为什么会这样?该模式对非图形数据结构(例如列表和数组)不是也很有用吗?与其他结构相比,访问者模式是否有某些东西使其特别适合树木?

正如 wiki 所说 visitor pattern:

A practical result of this separation is the ability to add new operations to existing object structures without modifying the structures. It is one way to follow the open/closed principle

是的,您可以将此模式用于列表和数组。在我看来,教程使用图形和树结构是因为他们想强调可以在不编辑现有代码的情况下添加新行为 类 存储在不简单的数据结构中。

让我通过 C# 展示一个数组示例。

抽象:

public interface IBicyclePart
{
    void Accept(IBicyclePartVisitor bicyclePartVisitor);
}

public interface IBicyclePartVisitor
{
    void Visit(Bicycle bicycle);

    void Visit(Treadle treadle);

    void Visit(Wheel wheel);

    void Visit(Seat Seat);
}

具体类:

public class Bicycle : IBicyclePart
{
    private IBicyclePart[] _parts;

    public Bicycle()
    {
        _parts = new IBicyclePart[] { new Seat(), new Treadle(), new Wheel() };
    }

    public void Accept(IBicyclePartVisitor computerPartVisitor)
    {
        for (int i = 0; i < _parts.Length; i++)
        {
            _parts[i].Accept(computerPartVisitor);
        }
        computerPartVisitor.Visit(this);
    }
}

public class Seat : IBicyclePart
{
    public void Accept(IBicyclePartVisitor bicyclePartVisitor)
    {
        bicyclePartVisitor.Visit(this);
    }
}

public class Wheel : IBicyclePart
{
    public void Accept(IBicyclePartVisitor bicyclePartVisitor)
    {
        bicyclePartVisitor.Visit(this);
    }
}

public class Treadle : IBicyclePart
{
    public void Accept(IBicyclePartVisitor bicyclePartVisitor)
    {
        bicyclePartVisitor.Visit(this);
    }
}   

自行车的“运行操作”:

public class BicyclePartRunOperationVisitor : IBicyclePartVisitor
{
    public void Visit(Bicycle bicycle)
    {
        Console.WriteLine("Bicycle is running");
    }


    public void Visit(Wheel wheel)
    {
        Console.WriteLine("Bike rider manages the wheel");
    }


    public void Visit(Treadle treadle)
    {
        Console.WriteLine("Bike rider rotates treadles");
    }


    public void Visit(Seat seat)
    {
        Console.WriteLine("Bike rider is at the seat");
    }
}

我们可以通过添加新操作“停止操作”来停止我们的自行车:

public class BicyclePartStopOperationVisitor : IBicyclePartVisitor
{
    public void Visit(Bicycle bicycle)
    {
        Console.WriteLine("Bicycle is running");
    }


    public void Visit(Wheel wheel)
    {
        Console.WriteLine("Bike rider manages the wheel");
    }


    public void Visit(Treadle treadle)
    {
        Console.WriteLine("Bike rider stops rotating treadles");
    }


    public void Visit(Seat seat)
    {
        Console.WriteLine("Bike rider is at the seat");
    }
}

然后你可以这样称呼它:

static void Main(string[] args)
{
    IBicyclePart computer = new Bicycle();
    computer.Accept(new BicyclePartRunOperationVisitor());
    // computer.Accept(new BicyclePartStopOperationVisitor()); // we are
        // using new operation without editing existing classes
}