2008-10-04 2 views
1

필자는 양방향 연결을 다루는 일반적인 방법과 수동 작성 Java 코드에서 역변환을 처리하는 방법을 찾고있었습니다.양방향 연결 및 역 업데이트를 관리하기위한 일반 Java 프레임

내가 무슨 말을하는 지 모르는 사람들을 위해 여기에 예제가 있습니다. 그 밑에는 (불만족스러운) 해결책의 현재 결과가 있습니다.

public class A { 
    public B getB(); 
    public void setB(B b); 
} 

public class B { 
    public List<A> getAs(); 
} 

이제 연결의 끝을 업데이트 할 때 일관성을 유지하기 위해 다른 쪽 끝도 업데이트해야합니다. 수동마다

a.setB(b); 
b.getA().add(a); 

또는 세터/게터에 일치하는 코드를 넣고 사용자 지정 목록 구현을 사용하여

.

의존성을 더 이상 사용할 수없는 구식, 유지 관리되지 않은 프로젝트 (https://e-nspire-gemini.dev.java.net/)를 발견했습니다. 필요한 코드를 자동으로 주입하는 데 사용되는 주석을 사용하여 문제를 처리합니다.

누구나이 일반적이고 눈에 거슬리지 않은 ala gemini에서 이것을 처리하는 또 다른 프레임 워크를 알고 있습니까? http://code.google.com/p/google-collections/이 (뿐만 아니라 호환이 잘 제네릭 사용) 자바 제네릭 호환

클래스 BiMap - - http://google-collections.googlecode.com/svn/trunk/javadoc/index.html?http://google-collections.googlecode.com/svn/trunk/javadoc/com/google/common/collect/package-summary.html 양방향 수 있습니다 (구글의 내부 코드에서)

답변

5

구글 모음

챠오, 엘마 협회.

이러한 클래스의 일부

은 당신 추상화 세터 밖으로, 당신은 이벤트 알림 메커니즘의 일종을 제공해야 할 것하지 않는 JDK 7

0

에 자신의 방법을 만들 것으로 예상된다. 오브젝트가 JavaBeans 인 경우 PropertyChangeSupport를 사용하고 속성 변경 이벤트를 실행하려고합니다.

변경 사항을 감지하는 다른 메커니즘이있는 경우 Glazed Lists는 목록 끝에서 연결 동기화를 처리하는 데 쉽게 사용할 수있는 ObservableElementList을 제공합니다 (즉, 목록에 A를 추가하면 <> 자동 호출). a.setB (b)). 다른 방향은 속성 변경 모니터링 (또는 동급)을 사용하여 쉽게 처리됩니다.

나는 이것이 일반적인 해결책이 아니라는 것을 알고 있지만, 그것이 일반적인 토대가 될 것 같아 보인다. 방법 짧은 당신이 일반적인 경우에 처리 할 수 ​​AOP 형 솔루션 (즉, 같은 ArrayList를 또는 무언가를 사용하여) -이 같은 일이 는 B 클래스의 특별한리스트의 구현이 필요없는 것

참고.

나는 또한 당신이 성취하고자하는 것이 데이터 바인딩의 성배라고 지적해야합니다. 필드 레벨에서의 바인딩 (getter와 setter와 같은 것)을위한 적절한 구현들이 있습니다 (예제는 JGoodies 바인딩과 JSR 295를 참조하십시오). 목록 유형 바인딩 (Glazed Lists, 위에 언급 됨)에 대한 하나의 실제 구현도 있습니다. 우리는 거의 모든 응용 프로그램에서 두 기술을 서로 사용하지만 사용자가 묻는 것만큼이나 추상적 인 것으로는 시도하지 않았습니다.

나는이를 설계 할 경우,이 같은 것을 볼 것입니다 :

AssociationBuilder.createAssociation(A a, Connector< A> ca, B b, Connector< B> cb, Synchronizer< A,B> sync) 

커넥터는 다양한 변경 알림 유형에 대한 단일 인터페이스를 허용하는 인터페이스입니다. 동기화 도구는 두 개체 중 하나가 변경 될 때마다 두 개체가 동기화되도록하기 위해 호출되는 인터페이스입니다.

sync(ChangeInfo info, A a, B b) // make sure that b reflects current state of a and vice-versa. 

ChangeInfo는 멤버가 변경된 데이터와 실제로 변경된 사항을 제공합니다. 우리는. 이 제네릭을 실제로 유지하려고한다면 프레임 워크 사용자에게이를 구현해야합니다.

위와 같이 설정하면 다양한 바인딩 조건을 충족하는 여러 미리 정의 된 커넥터 및 동기화 도구를 사용할 수 있습니다.

흥미롭게도 위의 메소드 서명은 JSR 295 createAutoBinding() 메소드 호출과 매우 유사합니다. 속성 개체는 Connector와 같습니다. JSR 295에는 Synchronizer가 없습니다 (대신 바인딩 전략이 ENUM으로 지정되어 있음). JSR 295는 property-> property 바인딩에서만 작동하며 한 객체의 필드 값을 다른 객체의 해당 객체 멤버십에 바인딩하려고합니다 그 (것)들을위한 테이블에조차 없다).

0

의미있게 말하면,이 칼은 동료가 될 것입니다. 저는 일관성을 유지하기위한 패키지 개인 메커니즘 (친구가없는 경우)을 제안합니다.

public final class A { 
    private B b; 
    public B getB() { 
     return b; 
    } 
    public void setB(final B b) { 
     if (b == this.b) { 
      // Important!! 
      return; 
     } 
     // Be a member of both Bs (hence check in getAs). 
     if (b != null) { 
      b.addA(this); 
     } 
     // Atomic commit to change. 
     this.b = b; 
     // Remove from old B. 
     if (this.b != null) { 
      this.b.removeA(this); 
     } 
    } 
} 

public final class B { 
    private final List<A> as; 
    /* pp */ void addA(A a) { 
     if (a == null) { 
      throw new NullPointerException(); 
     } 
     // LinkedHashSet may be better under more demanding usage patterns. 
     if (!as.contains(a)) { 
      as.add(a); 
     } 
    } 
    /* pp */ void removeA(A a) { 
     if (a == null) { 
      throw new NullPointerException(); 
     } 
     as.removeA(a); 
    } 
    public List<A> getAs() { 
     // Copy only those that really are associated with us. 
     List<A> copy = new ArrayList<A>(as.size()); 
     for (A a : as) { 
      if (a.getB() == this) { 
       copy.add(a); 
      } 
     } 
     return Collection.unmodifiableList(copy); 
    } 
} 

(Disclaime :.하지 테스트 또는 컴파일)

대부분 예외 안전 (예외 경우가 누수 될 수 있습니다). 스레드 안전성, 많은 - 많은, 성능, libraryisation 등 관심있는 독자에게 연습으로 남아 있습니다.

+0

답을 보내 주셔서 감사합니다.하지만이 문제를 일반적인 코드가 아닌 방식으로 다루는 솔루션을 찾고있었습니다. –

0

모든 제안에 감사드립니다. 그러나 아무도 내가 찾던 것과 거의 다가 가지 못했을 것입니다. 나는 틀린 방식으로 질문을 공식화했습니다.

나는 쌍둥이 자리 교체를 찾고 있었기 때문에 끝없는 검사와 특별한 List 구현으로 코드를 오염시키지 않으면 서 눈에 잘 띄지 않게 처리 할 수있었습니다. 이것은 Kevin이 제안한 AOP 기반 접근법을 요구합니다.

내가 좀 더 둘러 보았을 때 모든 소스와 소스와의 종속성이 포함 된 cnet에서 gemini 패키지를 발견했습니다. 의존성에 대한 누락 된 출처가 나를 사용하지 못하게하는 유일한 관심사였습니다. 이제 모든 소스가 사용 가능하므로 버그를 수정할 수 있습니다. 누구든지 다음을 찾으십시오. http://www.download.com/Gemini/3000-2413_4-10440077.html