2013-04-02 5 views
0

인터페이스를 구현하는 클래스가 있습니다. 이 인터페이스를 구현하는 또 다른 클래스가 있습니다.이 두 번째 클래스의 인스턴스가 클래스 구현을 지원합니다.위임 상용구는 어떻게 줄일 수 있습니까?

인터페이스에서 지정한 많은 메소드의 경우, 클래스는 두 번째 클래스로 곧바로 전달합니다.

public class MyClass implements MyInterface 
{ 
    private OtherClass otherClassInstance; // Also implements MyInterface. 
    // ... 
    void foo() { otherClassInstance.foo(); } 
    void bar() { otherClassInstance.bar(); } 
    void baz() { otherClassInstance.baz(); } 
    // ... 
} 

은 간단하게이 모든 것을 제거하는 것이 두 번째 클래스에서 내 클래스를 파생하지만 두 클래스 (공통 인터페이스를 구현 이외의) 서로 관련이 있기 때문에 이해가되지 않습니다. 그것들은 다른 것을 나타냅니다. 많은 클래스의 클래스 구현이 다른 클래스의 구현을 복사하기 때문에 발생합니다. 즉, 제 클래스는 두 번째 클래스 위에 구현되지만 두 번째 클래스의 서브 세트 자체는 아닙니다. 아시다시피 상속은 구현을 공유하지 않고 "is-a"관계를 표현하기위한 것이므로이 경우 부적절합니다.

This 조슈아 블로흐 (Joshua Bloch)의 이야기의 일부가 상황을 잘 보여줍니다.

Java에 위임에 대한 언어 지원이 없다는 것을 알고 있습니다. 그러나 적어도 클래스의 구현을 정리할 수있는 방법이 없으므로 중복되지는 않습니까? 사용

+0

Lemme은 ArrayList를 확장하려고하지만 모든 경우가 아니라 인터페이스가 그것을 잘라 내지 않습니다 ... 'MyList'가 대부분 ArrayList로 떨어지면 정말 이해할 수 있습니다. ArrayList를 확장하고 이에 따라 비 목록 목록을 처리합니다. – Shark

+0

일반적으로 "MyList"에 대한 이유를 확인합니다. 대부분의 경우 ArrayList이며 어떤 경우에는 특별한 동작이 필요합니다. 이 상황에서는 ArrayList를 사용하고 Wrapper/Adapter/명령을 빌드하여 기능을 제공합니다. 그리고 대부분 구아바를 찾아 무료로 필요한 부분을 얻습니다. –

+0

@Shark 아니요, ArrayList를 확장하고 싶지 않습니다. 나는'List'를 구현하기 위해 클래스를 만들고 있습니다.'ArrayList' 멤버는 단지 내 구현만을 뒷받침합니다. ArrayList 객체 대신에 MyList 객체를 사용하는 것은 의미가 없습니다. – Maxpm

답변

3

정말 실제 질문에 대한 답변 아닌 답변 :

내가 말하고 싶지만는 보일러와 함께 살고 있습니다. IDE에서 생성하도록하십시오. 예 : Netbeans에서 private ArrayList 필드를 추가하고 메서드를 표시 할 위치로 커서를 놓은 다음 alt-insert를 누르고 "대리자 메서드 생성 ..."을 선택하고 대리자를 만들 메서드를 누릅니다. 대화 상자가 열리면 제출되고 생성 된 메소드를 살펴보고 올바른 방법으로 작업하게됩니다.

조금 추합니다.하지만 소리가 나는 것처럼 하나의 클래스 만 다루는 경우에는 반사음을 엉망으로 만들기 시작하는 것이 좋습니다. 당신의 수업은 아마 당신이 끝내고 완전히 시험해 볼 수있는 종류의 수업 일 것입니다. 반영은 사라지지 않는 런타임 비용을 만듭니다. 이 경우 소스 파일에서 자동 생성 된 상용구를 사용하는 것이 좋습니다.

+0

성능에 대한 좋은 지적입니다. – Maxpm

+1

그리고 반성은 지저분하고, 오류가 발생하기 쉽고, 런타임에 불어납니다. – Jazzepi

1

첫 번째 방법 http://java.sun.com/javase/6/docs/api/java/lang/reflect/Proxy.html 페이지의 튜토리얼 http://docs.oracle.com/javase/1.4.2/docs/guide/reflection/proxy.html

당신이 반사 API

를 사용하는 방법의 처리를 관리하는 데 필요한 두 가지를 들어 특정 클래스

의 모든 호출을 차단 디스패처를 만들 수 있습니다 AOP를 사용하여

두 번째 방법

IDEA를 표현하도록 수정했습니다. 위의 튜토리얼에서 취한 코드는 조금 수정되었습니다 (invoke 메서드에서 youListImpl.getRealArrayList() 참조)

public class DebugProxy implements java.lang.reflect.InvocationHandler { 

    private YouListImpl youListImpl; 

    public static Object newInstance(Object obj) { 
    return java.lang.reflect.Proxy.newProxyInstance(
     obj.getClass().getClassLoader(), 
     obj.getClass().getInterfaces(), 
     new DebugProxy(obj)); 
    } 

    private DebugProxy(Object obj) { 
    this.obj = obj; 
    } 

    public Object invoke(Object proxy, Method m, Object[] args) 
    throws Throwable 
    { 
     Object result; 
    try { 
     System.out.println("before method " + m.getName()); 
     result = m.invoke(youListImpl.getRealArrayList(), args); 
     } catch (InvocationTargetException e) { 
     throw e.getTargetException(); 
     } catch (Exception e) { 
     throw new RuntimeException("unexpected invocation exception: " + 
         e.getMessage()); 
    } finally { 
     System.out.println("after method " + m.getName()); 
    } 
    return result; 
    } 
} 
+0

이 경우 리플렉션 API를 사용할 수있는 구체적인 예를 제공 할 수 있습니까? – Maxpm

+0

@Maxpm은 스냅 샷을 배치하기 만합니다. – Dewfy