2010-05-22 3 views
3

동일한 인터페이스의 일부 인스턴스를 다양한 방법으로 결합하는 인터페이스를 구현하는 가장 좋은 방법은 무엇입니까? 여러 인터페이스에 대해이 작업을 수행해야하며 핵심 생산 시스템에 필요하기 때문에 상용구를 최소화하면서도 여전히 우수한 효율성을 달성하고 싶습니다.다양한 방법으로 동일한 인터페이스의 일부 인스턴스를 결합하는 인터페이스를 프로그래밍 방식으로 구현

다음은 문제의 스케치입니다. 추상적으로

, 나는 인스턴스를 받아 다양한 연결자 지정 일반적인 결합기 클래스가 있습니다

Interface Foo { 
    String bar(int baz); 
} 
: 이제

class Combiner<I> { 
    I[] instances; 

    <T> T combineSomeWay(InstanceMethod<I,T> method) { 
    // ... method.call(instances[i]) ... combined in some way ... 
    } 

    // more combinators 
} 

을의 나는 많은 다른 사람의 사이에서 다음과 같은 인터페이스를 구현하고 싶은 말은하자

나는 다음과 같은 코드로 끝내고 싶다 :

class FooCombiner implements Foo { 
    Combiner<Foo> combiner; 

    @Override 
    public String bar(final int baz) { 
    return combiner.combineSomeWay(new InstanceMethod<Foo, String> { 
     @Override public call(Foo instance) { return instance.bar(baz); } 
    }); 
    } 
} 

인터페이스에 많은 메소드가있는 경우 신속하고 길게 느껴질 수 있습니다. 자바 리플렉션 API의 동적 프록시를 사용하여 그러한 인터페이스를 구현할 수는 있지만 리플렉션을 통한 메소드 액세스는 백 배 느리다는 것을 알고 있습니다. 이 경우 상용구 및 반성의 대안은 무엇입니까?

+0

이것은 상당히 큰 제목이었습니다! – Secko

답변

2

동적 프록시를 제안했을 것입니다. 요즘 일반적인 메소드 호출보다 속도가 너무 느립니다. 반복적 인 메소드 호출 속도를 높이기 위해 리플렉션이 꽤 많은 마법을 사용한다고 들었습니다. (그리고 만약 그것이 100 배 느리다면 확실히 알 수 있겠습니까? 그렇습니다. 질문을 다시 읽으십시오.)

그렇지 않으면 기본적으로 다음과 같은 해결책을 가지고 있습니다 : Command 객체 사용 인터페이스의 각 메소드를 랩핑합니다. 그런 다음 인터페이스 컬렉션의 각 인스턴스를 명령 객체에 전달하여 처리 할 수 ​​있습니다.

물론, 용감하고 모험심이 있다면 커맨드 객체의 구현을 생성하고 cglib, javassist, orther dynamic bytecode generator을 사용하여 동적 클래스 생성을 사용하여 결합기 인터페이스를 구현할 수 있습니다. 이것은 상용구를 피할 것입니다.

또한 aspect를 사용하여 약간의 성공을 거둘 수 있습니다. 특히 컴파일 시간 또는로드 시간 짜기로 aspectJ를 사용하면 반사 오버 헤드를 피할 수 있습니다. 미안하지만 세부 사항을 알려줄 수는 없어.

+0

동적 프록시를 사용하여 끝났으며 훨씬 더 깨끗합니다. 또한 속도가 느린 경우 메소드 액세스가 빠르기 때문에 눈에 띄지 않습니다. – namin

1

당신은 당신의 컴을 취소 할 수 있습니다 :

@Override 
public String bar(int baz) 
{ 
    //for (Foo f:combiner.combineSomeWay())// returns Iterator<Foo> 
    for (Foo f:combiner) //combiner must implement Iterable<Foo> or Iterator<Foo> 
    { 
     // In case of several ways to combine 
     // add() method should call some temp object 
     // in combiner created (or installed) by 
     // combineSomeWay. 
     // The best temp object to use is Iterator 
     // returned by combiner.combineSomeWay(); 
     combiner.add(f.bar(baz));// or addResult, or addCallResult 
    } 
    // clear (or uninstall) temp object and result 
    // thats why get* method 
    // name here is bad. 
    return combiner.done(); 
} 

아니 한 줄하지만 쉽게 이해 할 수 있습니다. 당신의 메소드가 예외를 던지면 더 복잡해질 것입니다. try/catch 블록과 addException 메소드가 필요합니다.

+0

나쁜 생각은 아니지만 제 경우에는 결합 자에게 메소드를 호출할지 여부를 결정해야합니다. 예를 들어, 하나의 결합자는 첫 번째 인스턴스의 메소드를 호출하고 다른 메소드는 무시하는 것입니다.). 어쨌든 고마워, 좋은 비꼬아. – namin

+0

이것은 정확하게 컬렉션 대신 iterator를 사용하는 이유입니다. Combiner는 메서드를 호출 할 필요가있을 때 iterator를 통해 객체를 제공해야하며 iterator가 add 메서드의 인수를 기반으로 반환 할 다음 요소를 결정할 수 있습니다. 연속성은 결합자를 많이 단순화하지만 Java는 아직 지원하지 않습니다. –

+0

아, 이것은 영리한 ...어쨌든, 각 메소드에서 for 루프를 사용하는 것은 여전히 ​​보일러 방식입니다. 하지만 좋은 속임수. – namin