访问者模式与树状遍历API的LINQ样式流畅语法

时间:2011-05-28 14:09:57

标签: c# linq fluent tree-traversal visitor-pattern

我正在考虑重构一个开源项目Afterthought,以使其更直观易用。基本思想是,在Afterthought中创建修订的开发人员将修改特定的.NET类型,并有机会修改类型本身,以及属性,方法,事件,构造函数等列表(树)。我在内部Microsoft CCI Metadata使用的API在其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而不是覆盖方法的列表进行交互,将所有代码写在一个地方(或他们选择的地方)。显然,这种方法的性能稍差(更多迭代等),但除此之外,还有哪些缺点?

1 个答案:

答案 0 :(得分:3)

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

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

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