【问题标题】:Adding a bifurcation to a fluent interface builder向流畅的界面构建器添加分叉
【发布时间】:2010-12-30 09:25:42
【问题描述】:

我有一个小框架,可以让我创建一个管道和过滤器系统。 我想到了使用流畅的接口来构建管道和过滤器系统:

        PipeFilter pipeFilter = PipeFilter.StartBuild()
            .AddFilter(new SomeFilter1())
            .AddFilter(new SomeFilter2())
            .AddFilter(new SomeFilter3())
            .AddFilter(new SomeFilter4())
            .Build();

显示的代码按预期工作。这是系统的“图片”:

SomeFilter1 -> SomeFilter2 -> SomeFilter3 -> SomeFilter4

现在,有一种过滤器,它不是一个输出,而是两个。我称之为bifurcation。 下面是一个带有bifurcation 的系统示例:

              |-> SomeFilter2 -> SomeFilter3
SomeFilter1 --|
              |-> SomeFilter4

我想实现这样的东西:

        PipeFilter pipeFilter = PipeFilter.StartBuild()
            .AddFilter(new SomeFilter1())
            .AddBifurcation()
                .Output1()
                    .AddFilter(new SomeFilter2())
                    .AddFilter(new SomeFilter3())
                .Output2()
                    .AddFilter(new SomeFilter4())
            .Build();

但我似乎无法做到这一点。这甚至可能吗? 在第一个示例中,我只需要一个PipeFilterBuilder(由PipeFilter.StartBuild() 返回)。在第二个示例中,我尝试创建其他类型的构建器来混合使用,但这似乎无济于事。

忘了提一下,我的想法是我可以在任何我想要的地方嵌套分叉,也就是说,我可以得到满是树枝的“树”!

有人可以帮忙吗?

【问题讨论】:

    标签: c# java oop fluent-interface


    【解决方案1】:

    我会走下面的路

    PipeFilter pipeFilter = PipeFilter.StartBuild()
            .AddFilter(new SomeFilter1())
            .AddBifurcation(
                  withOutput(1)
                     .AddFilter(new SomeFilter2())
                     .AddFilter(new SomeFilter3()), /* this separates first and second output */
                  withOutput(2)
                    .AddFilter(new SomeFilter4())
                  )
            .Build();
    

    在更多格式方面,我将 Bifurcation 类定义为 Filter 接口的实现者。

    分叉可以有任意数量的输出过滤器,使用Output 对象链接。为了区分这些输出对象,它们都有一个索引。

    因此,addBifurcation 创建一个新的 Bifurcation 对象并添加它,而 withOutput(int) 是创建 Output 对象的静态方法,它具有所有必需的方法。请注意,这意味着您摆脱了 Builder 和已构建对象之间的经典区别,转而使用在 Filter 的基本接口中定义 Builder 方法的代码。

    【讨论】:

      【解决方案2】:

      我认为您受到符号的限制。在最低级别,您的过滤系统可以由原始过滤器以及顺序和并行组合组成。你的第一个例子可以写成(用伪代码):

      pipeFilter = Seq(new SomeFilter1(), 
                       Seq(new SomeFilter2(), 
                           Seq(new SomeFilter3(), new SomeFilter4())));
      

      有了这样的接口,如何在接口中添加并行——或者实际上是任何其他类型的组合——是完全显而易见的:

      pipeFilter = Seq(new SomeFilter1(), 
                      Parallel(Seq(new SomeFilter2(), new SomeFilter3()),
                               Seq(new SomeFitler4())));
      

      虽然看起来很麻烦,但我建议以这种方式构建您的接口(称为“功能性”,而不是“命令式”接口),然后编写方便的方法来减少一些结构负担,例如 @ 的变体987654323@ 和 Parallel 接受任意数量的参数 - 但最好让它们简单地委托给二进制变体的折叠。

      为了详细说明这里更微妙的设计问题,您正在使用的类或接口是一个过滤器builder,而不是一个过滤器本身。 ParallelSeq 是该类的方法。这使您可以选择以多种方式实现组合器以进行多种解释。我会这样写界面:

      interface FilterBuilder<Filter> {
          Filter Seq(Filter a, Filter b);
          Filter Parallel(Filter a, Filter b);
      }
      

      它可能不适合您的需求,但它是一种不错、灵活的设计模式,似乎并不广为人知。

      【讨论】:

        【解决方案3】:

        可以按照您的设计实现系统。

        除了PipeFilterBuilder,您不需要任何构建器,但您需要一个能够表示过滤器树的数据结构。然后您的PipeFilterBuilder 持有对该结构的引用并跟踪当前插入点。

        您对PipeFilterBuilder 执行的任何操作都需要更新插入点并返回构建器本身(this)。调用AddBifurcation 会将当前插入点添加到堆栈中。相反,Output2 会将插入点设置为从堆栈中弹出的值。其他功能应该是相当微不足道的。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2022-08-19
          • 2010-09-19
          • 1970-01-01
          • 2018-07-08
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多