2010-12-30 2 views
2

파이프 시스템을 만들 수있는 작은 프레임 워크가 있습니다. & 필터 시스템. 나는 파이프 & 필터 시스템을 구축 유창한 인터페이스를 사용하는 아이디어했다 : 예상대로 표시 코드가 작동유창한 인터페이스 빌더에 분기점 추가

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

합니다. 여기에 시스템의 "그림"이 있습니다 :

SomeFilter1 -> SomeFilter2 -> SomeFilter3 -> SomeFilter4 

이제는 하나의 출력 대신 2 개의 출력이있는 종류의 필터가 있습니다. 나는 그것을 bifurcation라고 부른다. 나는이 같은 것을 구현하고 싶습니다

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

: 는 여기 bifurcation있는 시스템의 예입니다

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

그러나 나는 바로 그것을 얻을 수없는 것 같다. 이것을 할 수 있습니까? 첫 번째 예에서는 PipeFilterBuilder (PipeFilter.StartBuild()에 의해 반환 됨)이 필요했습니다. 이 두 번째 예제에서는 믹스에 포함시킬 다른 종류의 빌더를 만들려고 시도했지만 아무 소용이없는 것 같습니다.

언급하는 것을 잊었을 때, 나는 원하는 곳 어디에서나 분기점을 중첩시킬 수 있다는 생각을 들었습니다. 즉, 나뭇 가지로 가득 찬 "나무"를 얻을 수있었습니다.

아무도 도움이 될 수 있습니까?

답변

2

나는 내가 Filter 인터페이스의 구현으로 분기점 클래스를 정의, 더 형식 측면에서 다음과 같은 방법을

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

을 갈 것입니다.

분기에는 Output 개체를 사용하여 연결된 여러 개의 출력 필터가있을 수 있습니다. 이러한 출력 개체를 구별하기 위해 모두 인덱스가 있습니다.

결과적으로 addBifurcation은 새로운 Bifurcation 개체를 만들고 추가하며, withOutput(int)은 필요한 모든 메서드가있는 Output 개체를 만드는 정적 메서드입니다. 이 점은 빌더 메소드가 필터의 기본 인터페이스에 정의 된 코드를 사용하여 빌더와 빌드 된 객체 간의 클래식 구분을 제거한다는 의미입니다.

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은 임의의 수의 인수를 취하지 만 아마도 b e 바이너리 변종의 폴드 (fold)에 위임하는 것이 가장 좋습니다.

여기서 subtler 디자인 문제를 자세히 설명하기 위해 작업중인 클래스 또는 인터페이스는 필터 빌더이며 필터 자체는 아닙니다. ParallelSeq이 해당 클래스의 메소드입니다. 이렇게하면 여러 해석을 위해 여러 방법으로 연결자를 구현할 수있는 옵션이 제공됩니다. 이 같은 인터페이스를 작성합니다

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

그것은 당신의 요구에 적합하지 않을 수 있습니다,하지만 그것은 널리 알려하지 않는 것 멋진 유연한 디자인 패턴입니다.

1

시스템을 설계 한대로 구현할 수 있습니다.

PipeFilterBuilder 이외의 빌더가 필요하지 않지만 필터 트리를 나타낼 수있는 데이터 구조가 필요합니다. PipeFilterBuilder은이 구조에 대한 참조를 보유하고 현재 삽입 점을 추적합니다.

PipeFilterBuilder에서 수행하는 조작은 삽입 지점을 갱신하고 빌더 자체 (this)를 리턴해야합니다. AddBifurcation을 호출하면 현재 삽입 포인터를 스택에 추가합니다. 반대로 Output2은 스택에서 튀어 나온 값에 삽입 지점을 설정합니다. 다른 함수는 매우 사소한 것이어야합니다.

관련 문제