Я думаю, что вы ограничены вашей записью. На самом низком уровне ваша система фильтрации может состоять из примитивных фильтров, а также последовательных и параллельных композиций. Ваш первый пример может быть написан (в псевдокоде):
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())));
Хотя это может показаться громоздким, я бы предложил создать ваш интерфейс таким образом (называемый «функциональным», а не «императивным» интерфейсом), а затем написать удобные методы, чтобы уменьшить некоторые структурные нагрузки, например, варианты 1007 * и Parallel
, которые принимают произвольное количество аргументов - но, вероятно, было бы лучше, если бы они просто делегировали до сгибов двоичных вариантов.
Чтобы подробнее разобраться с более тонкой конструкцией, класс или интерфейс, с которым вы работаете, - это фильтр builder , а не сам фильтр. Parallel
и Seq
являются методами этого класса. Это дает вам возможность реализовать комбинаторы несколькими способами для нескольких интерпретаций. Я бы написал такой интерфейс:
interface FilterBuilder<Filter> {
Filter Seq(Filter a, Filter b);
Filter Parallel(Filter a, Filter b);
}
Возможно, он не идеален для ваших нужд, но это хороший, гибкий шаблон проектирования, который, кажется, не очень известен.