2

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

        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())。在第二个示例中,我尝试创建其他类型的构建器来混合使用,但这似乎无济于事。

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

任何人都可以对此有所帮助吗?

4

3 回答 3

2

我会走以下路

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 对象并添加它,而 whilewithOutput(int)是创建Output对象的静态方法,它具有所有必需的方法。请注意,这意味着您摆脱了 Builder 和已构建对象之间的经典区别,转而使用在 Filter 的基本接口中定义 Builder 方法的代码。

于 2010-12-30T09:33:23.260 回答
1

可以按照您设计的方式实施该系统。

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

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

于 2011-01-12T03:43:41.417 回答
1

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

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())));

虽然看起来很麻烦,但我建议以这种方式构建您的界面(称为“功能性”,与“命令式”界面相对),然后编写方便的方法来减少一些结构负担,例如SeqParallel的变体任意数量的参数 - 但最好让那些简单地委托给二进制变体的折叠。

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

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

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

于 2010-12-30T09:35:35.827 回答