首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >分类访客

分类访客
EN

Code Review用户
提问于 2011-02-07 18:29:30
回答 1查看 216关注 0票数 4

我开始用自上而下的测试来编写代码。我的第一个版本是这样的:

代码语言:javascript
复制
public class Worker
{
  public void Execute(Foo foo)
  {
     //Do X on Foo
     //Do Y on Foo
     //Do Z on Foo

     //Get Bar from Foo

     //Do A on Bar
     //Do B on Bar
     //Do C on Bar
  }
}

然后这个开始长得更多。所以,我需要添加更多的动作,比如X,Y,Z

我将代码重构为如下内容:

代码语言:javascript
复制
public interface IFooVisitor
{
  void Visit(Foo foo);
}

public interface IBarVisitor
{
  void Visit(Bar bar);
}

public class Worker
{
  public Worker(
            IEnumerable<IFooVisitor> fooVisitors, 
            IEnumerable<IBarVisitor> barVisitors)
  { ... }
  public void Execute(Foo foo)
  {
    foreach(var fooVisitor in fooVisitors) { fooVisitor.Visit(foo); }
    var bar = getbarfromfoo(foo);
    foreach(var barVisitor in barVisitors) { barVisitor.Visit(bar); }
  }
}

代码要干净得多,但问题是,在执行访问者时,我需要一些特定的命令。因此,一种选择是向每个访问者添加一个属性,如:

代码语言:javascript
复制
public int Priority {get { return 1; } }

这个项目是开源的,完整的代码是这里

  • IAbcVisitor是ICloneVisitor
  • IXyzVisitor是IPostWeaveAction
EN

回答 1

Code Review用户

回答已采纳

发布于 2011-02-07 19:34:30

你考虑过使用命令链而不是访客吗?

代码语言:javascript
复制
public interface IFooChainLink
{
    void Execute(Foo foo);
}

public interface IBarChainLink
{
    void Execute(Bar bar);
}

public class Worker
{
    public Worker(IFooChainLink fooChain, IBarChainLink barChain)
    { ... }

    public void Execute(Foo foo)
    {
        fooChain.Execute(foo);
        var bar = getbarfromfoo(foo);
        barChain.Execute(bar);
    }
}

你的链环应该是这样的

代码语言:javascript
复制
public DoXToFoo : IFooChainLink
{
    private static IFooChainLink NextInChain = new DoYToFoo();

    public void Execute(Foo foo)
    {
        // DO STUFF HERE
        NextInChain.Execute(foo);
    }
}

您还需要一个EndOfFooChain

代码语言:javascript
复制
public EndOfFooChain : IFooChainLink
{
    public void Execute(Foo foo)
    {
        // DO NOTHING HERE
    }
}

您可能需要一个在调用代码中更有意义的起点,例如

代码语言:javascript
复制
public FooChainActivator : IFooChainLink
{
    private static IFooChainLink NextInChain = new DoXToFoo();

    public void Execute(Foo foo)
    {
        // DO NOTHING
        NextInChain.Execute(foo);
    }
}

这样,您的链就可以很好地排序,并且可以很容易地将链接插入到链中,甚至连开始和结束都不需要更改调用代码。

如果您希望在一个地方声明您的链序列,您可以将NextInChain作为构造函数参数传递到链的每一层,这样您的调用代码就变成了

代码语言:javascript
复制
var worker = new Worker(
                 new DoXToFoo(
                 new DoYToFoo(
                 new DoZToFoo(
                 new EndOfFooChain()))),
                 new DoAToBar(
                 new DoBToBar(
                 new DoCToBar(
                 new EndOfBarChain())))
              );

这有一个额外的优势,您可以向链中的链接发送参数,但我觉得这比在链接本身中定义NextLinkInChain要麻烦一些。

我想这是个人偏好的问题。

票数 4
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/677

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档