C# 向fluent界面生成器添加分支

C# 向fluent界面生成器添加分支,c#,java,oop,fluent-interface,C#,Java,Oop,Fluent Interface,我有一个小框架,允许我创建管道和过滤器系统。 我的想法是使用fluent接口构建管道和过滤器系统: PipeFilter pipeFilter = PipeFilter.StartBuild() .AddFilter(new SomeFilter1()) .AddFilter(new SomeFilter2()) .AddFilter(new SomeFilter3()) .AddFi

我有一个小框架,允许我创建管道和过滤器系统。 我的想法是使用fluent接口构建管道和过滤器系统:

        PipeFilter pipeFilter = PipeFilter.StartBuild()
            .AddFilter(new SomeFilter1())
            .AddFilter(new SomeFilter2())
            .AddFilter(new SomeFilter3())
            .AddFilter(new SomeFilter4())
            .Build();
显示的代码按预期工作。以下是系统的“图片”:

SomeFilter1 -> SomeFilter2 -> SomeFilter3 -> SomeFilter4
现在,有一种滤波器,它不是一个输出,而是两个输出。我称之为分歧。 以下是具有
分叉的系统示例:

              |-> SomeFilter2 -> SomeFilter3
SomeFilter1 --|
              |-> SomeFilter4
我想实现如下内容:

        PipeFilter pipeFilter = PipeFilter.StartBuild()
            .AddFilter(new SomeFilter1())
            .AddBifurcation()
                .Output1()
                    .AddFilter(new SomeFilter2())
                    .AddFilter(new SomeFilter3())
                .Output2()
                    .AddFilter(new SomeFilter4())
            .Build();
interface FilterBuilder<Filter> {
    Filter Seq(Filter a, Filter b);
    Filter Parallel(Filter a, Filter b);
}
但似乎我就是做不好。这有可能吗? 在第一个示例中,我只需要一个
PipeFilterBuilder
(由
PipeFilter.StartBuild()返回)。在第二个例子中,我尝试创建其他类型的构建器来加入到混合中,但这似乎是徒劳的

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


有谁能帮上忙吗?

我会走下面的路

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();
在更多的格式术语中,我将分叉类定义为
Filter
接口的实现者

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


因此,addBranch创建一个新的分叉对象并将其添加,而
withOutput(int)
是一个静态方法,创建一个
Output
对象,该对象具有所有必需的方法。请注意,这一点意味着您摆脱了构建器和构建对象之间的传统区别,转而使用在过滤器的基本接口中定义构建器方法的代码。

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

有了这样一个接口,如何向接口中添加parallel(或任何其他类型的组合器)是显而易见的:

pipeFilter = Seq(new SomeFilter1(), 
                Parallel(Seq(new SomeFilter2(), new SomeFilter3()),
                         Seq(new SomeFitler4())));
虽然看起来很麻烦,但我建议您以这种方式构建接口(称为“函数式”接口,与“命令式”接口相对应),然后编写方便的方法来减轻一些结构负担,例如,
Seq
Parallel
的变量可以接受任意数量的参数,但最好是将这些变量简单地委托给二进制变量的折叠

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

        PipeFilter pipeFilter = PipeFilter.StartBuild()
            .AddFilter(new SomeFilter1())
            .AddBifurcation()
                .Output1()
                    .AddFilter(new SomeFilter2())
                    .AddFilter(new SomeFilter3())
                .Output2()
                    .AddFilter(new SomeFilter4())
            .Build();
interface FilterBuilder<Filter> {
    Filter Seq(Filter a, Filter b);
    Filter Parallel(Filter a, Filter b);
}
接口过滤器生成器{
过滤器顺序(过滤器a、过滤器b);
过滤器并联(过滤器a、过滤器b);
}

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

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

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

PipeFilterBuilder
上执行的任何操作都需要更新插入点并返回生成器本身(
this
)。调用
add分叉
会将当前插入点添加到堆栈中。相反,
Output2
会将插入点设置为从堆栈弹出的值。其他功能应该相当简单