2

我正在考虑重构一个开源项目Afterthought,使其使用起来更直观。基本思想是,在 Afterthought 中创建修改的开发人员将修改特定的 .NET 类型,并有机会修改类型本身以及属性、方法、事件、构造函数等列表(树)。我在内部使用的 API微软 CCI 元数据在他们的 API 中广泛使用了访问者模式,所以我在 Afterthought 中采用了类似的方法,如下所示:

public override void Amend()
{
    // Amend the type here, add properties, add methods, etc.
}

public override void Amend<TProperty>(Property<TProperty> property)
{
    // Amend properties here
    if (property.Name == "Result")
    {
        // Modify Result property
    }
}

public override void Amend(Method method)
{
    // Amend methods here
    if (method.Name == "Add")
    {
        // Modify Add method
        method.Implement(TInstance instance, int x, int y) => x + y);
    }
}

但是,我发现访问者模式实际上最终会将解决目标问题的代码(例如检测类库)重新分配到一系列不同的方法中,这些方法专注于树的各个方面。对于创建 API 的开发人员来说,这很容易实现,但消费者必须以某种不自然的方式将他们的代码分散开来。所以我提出了一个问题,与仅将树公开为列表并利用 LINQ 样式的方法相比,vistor 模式有什么好处?

这是我正在考虑的替代语法:

public override void Amend()
{
    // Do everything here, possibly calling methods just to organize the code

    // Modify Add method
    Methods.Named("Add").WithParams<int, int>()
        .Implement((instance, x, y) => x + y);
}

因此,在这种情况下,修正案的作者可以通过与公开 fluent/LINQ API 而不是覆盖方法的列表交互,将所有代码写在一个地方(或他们选择的地方)。显然这种方法的性能稍差(更多迭代等),但除此之外,还有什么缺点?

4

1 回答 1

3

访问者模式可帮助您避免创建将测试访问元素类型的语句ifswitch避免这些陈述通常被认为是一种良好的做法。如果您实现的操作没有区分可以访问的各种可能类型的元素,那么,是的,访问者模式不会给您带来任何优于您的替代方法的任何其他方法。

问题可能在于对访问者模式的理解:它主要是关于在不提供此功能的语言中实现双分派,或者(这是 C# 的情况)使用双分派带来相当大的性能问题。这与树遍历无关。它甚至可以用于不形成层次结构的类。GoF 书说,遍历算法可以由访问者本身实现,也可以由访问的元素实现,甚至可以由客户端实现。

编辑:我再次仔细阅读了您的问题,我认为您的方法是访问者模式的替代实现,其中访问者不是一个类,而是一组 lambda 函数。

于 2011-05-28T14:28:28.777 回答