2

パイプとフィルターシステムを作成できる小さなフレームワークがあります。私は流暢なインターフェースを使ってパイプとフィルターシステムを構築するという考えを持っていました:

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

示されているコードは期待どおりに機能します。システムの「写真」は次のとおりです。

SomeFilter1 -> SomeFilter2 -> SomeFilter3 -> SomeFilter4

現在、1 つの出力ではなく 2 つの出力を持つ一種のフィルターがあります。私はそれを呼びます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()) が必要でした。この 2 番目の例では、他の種類のビルダーを作成してミックスに取り入れようとしましたが、それは役に立たないようです。

言い忘れましたが、アイデアは、分岐を好きな場所にネストできるということです。つまり、枝でいっぱいの「木」を得ることができます!

誰でもこれで助けになれますか?

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 オブジェクトを作成して追加しますが、 は必要なすべてのwithOutput(int)メソッドを持つオブジェクトを作成する静的メソッドです。Outputこの点は、Builder メソッドが Filter の基本インターフェースで定義されているコードを支持して、Builder と構築されたオブジェクトの間の古典的な区別を取り除くことを意味することに注意してください。

于 2010-12-30T09:33:23.260 に答える
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())));

面倒に思えるかもしれませんが、この方法でインターフェイスを構築し (「命令型」インターフェイスではなく「関数型」インターフェイスと呼ばれます)、便利なメソッドを記述して構造的な負担を軽減することをお勧めしSeqますParallel。引数の数は任意ですが、バイナリ バリアントのフォールドに単純にデリゲートするのがおそらく最善でしょう。

ここで微妙な設計上の問題を詳しく説明すると、使用しているクラスまたはインターフェイスはフィルタービルダーであり、フィルター自体ではありません。 ParallelおよびSeqそのクラスのメソッドです。これにより、複数の解釈のために複数の方法でコンビネータを実装するオプションが提供されます。私は次のようにインターフェースを書きます:

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

あなたのニーズには完璧ではないかもしれませんが、広く知られているようには見えない、素晴らしく柔軟なデザイン パターンです。

于 2010-12-30T09:35:35.827 に答える
1

設計したとおりのシステムを実装することが可能です。

以外のビルダーは必要ありませんがPipeFilterBuilder、フィルターのツリーを表現できるデータ構造が必要になります。次にPipeFilterBuilder、この構造への参照を保持し、現在の挿入ポイントを追跡します。

実行する操作はすべてPipeFilterBuilder、挿入ポイントを更新し、ビルダー自体を返す必要があります ( this)。を呼び出すAddBifurcationと、現在の挿入ポイントがたとえばスタックに追加されます。逆にOutput2、スタックからポップされた値に挿入ポイントを設定します。他の機能はかなり簡単なはずです。

于 2011-01-12T03:43:41.417 に答える