2010-07-06 9 views
0

클래스 A에는 일련의 핸들러가 있습니다. 이벤트가 발생하면 클래스 B의 다른 스레드가 클래스 A의 해당 처리기를 호출합니다 (클래스 B는 A 관찰자 관찰 가능 클래스에 대한 참조를가집니다). A 클래스의 상응하는 메소드에서 이벤트를 처리 할 때, 결국 이벤트는 eventListener (클래스 C는 나에 의해 생성되지 않음)로 발생합니다. 제 질문은 다음과 같습니다 : eventListeners (나에 의해 구현되지 않음) 역할을하는 클래스에서 클래스 A의 처리 메서드를 "숨기고"클래스 B에만 "가시적/가시적"이 될 수있는 패턴이 있습니까? 내가 구현하는)?제 3 자 클래스에서 메소드를 숨기는 Java/패턴

원래 질문을 수정 중입니다. 방법과 처리기가 많이 나는 약

public class Csystem() 
{ 

    private AListener listener;//implements an event listener (the class C in my question) 

//some methods here 
public void handleEventIncoming(Event e){ 
//Do some logic here 
    listener.raiseEvent(e); 
} 
public void handleEventOutgoing(Event e); etc 


} 

CSystem을 이야기하고있다 내가 가진 클래스 Csystem은 본질적으로 내 코드에 다른 구성 요소의 다른 개발자를위한 인터페이스입니다 클래스입니다. 다른 개발자는 AListener 클래스 (클래스 A)의 자체 버전을 작성하고 코드에 Csystem을 사용합니다. 이벤트가 어딘가에 발생할 때마다 클래스 B는 CSystem

의 이벤트 핸들러에 이벤트를 전달합니다 (예를 들어, 네트워크에 메시지가 도착)
public class Dispatch{ 
//This is class B 
private CSystem s; 

private void event_occured(Event e) 
{ 
    s.handleEventIncoming(e); 
} 
} 

} 내 문제는 모두 (나에 의해 구현) 클래스 파견 및 클래스 AListener "참조하십시오"CSystem의 동일한 인터페이스. 나는 Alistener를 구현하는 개발자가 CSystem의 다른 뷰를보고 "볼"수 있고 공개 메서드 만 사용할 수 있기를 바랍니다. 나는 누군가가 실제로 사용할 수없는 방법을 (핸들러는 운영자에 의해서만 사용되는 의미가 있음) 보는 것은 좋은 생각이라고 생각하지 않는다. 이것을 달성하기위한 패턴이 있는가?

감사합니다.

답변

3

인터페이스를 사용하십시오. B와 A의 관계는 B가 정의하고 A가 구현하는 인터페이스를 통해서만 가능합니다.

그래서 B의 관점에서 컴파일 타임에 A를 가져 오거나 A의 정의에 액세스 할 수 없습니다.

질문에 대한 응답으로 편집 됨.

나는 당신이 어떤 패키지 X · Y의 클래스 당신에 의해 unchangable

기존의 C, 코드를 믿습니다;

Class CEvent { 
    // some event definition 
}; 

Class C { 
    public void callWhenitHappens(CEvent theEvent) { 
     // do something 
    } 
} 

는 --- 코드는 ---

package p.q; 
public Class A implements BEventInterface { 

    public void bEventHappened(BEvent theBEvent){ 
     // make a C event 
     myC.callWhenitHappens(theCEvent); 
    } 

} 

쓰기 그리고 당신의 관심사는 사람는,도를 포함한 C가 bEventHappened() 메서드를 호출 할 수 있다는 것입니다.

내 생각에 너는 드문 문제에 관심이있다. 왜 누군가가 A 객체를 만들고 그 일을하는 데 어려움을 겪을까요? 그러나 몇 가지 가능성이 있습니다 :

1). A와 B가 같은 패키지에 있다면, A와 그것의 방법을 공개하지 마십시오. 오직 B만이 그들을 볼 필요가 있습니다. 그래서 패키지 범위에서 이것은 작동 할 것입니다.

2). 익명 내부 클래스. 여기서 public 메서드가없는 ia 클래스이므로 C는 사용할 수 없지만 B는 사용할 수있는 익명의 내부 클래스에 public 메서드를 사용합니다.

package p.q; 

public class B { 

public class BEvent { 
    public String what; 
} 

private BListener myListener; 

private void fireEvent(){ 
    myListener.listen(new BEvent()); 
} 

public void registerListener(BListener listener){ 
    myListener = listener; 
} 

} 

package x.y.z; 

public class C { 
public class CEvent { 
    public String what; 
} 

public void callWhenitHappens(CEvent event){ 
    //e3c 
} 

}

+0

안녕하세요, 다음을 의미합니까? 공용 클래스 B { 인터페이스 처리기 { public void handleEv1(); public void handleEv1(); } 등 } 클래스 A는 처리기를 구현합니다. { public void handleEv1(); public void handleEv1(); 등 } 하지만이 디자인으로 공개 된 이후 여전히 C에서 액세스 할 수있는 핸들러가 아닙니까? 아니면 내가하는 말을 오해하니? – akmer

+0

그러나 A가 이벤트를 C로 보내고 C가 A에 대해 아무것도 모르고, A가 작성되기 훨씬 전에 컴파일되었으므로 anA.myMethod()에 대해 알고있는 코드가 C에 없을 수 있습니다. – djna

+0

답장을 보내 주셔서 감사합니다. 내 문제는 다음과 같다. (내 생각이 틀릴 수도있다.) 나는 클래스 B와 클래스 C 사이의 경계 역할을하는 클래스 A를 가지고있다. 클래스 A는 클래스 C가 리스너로 등록되어있다. 클래스 B는 이벤트가 발생하면 A의 handlerMethods를 호출하고 메서드는 일부 처리를 수행하고 이벤트를 C로 발생시킵니다. 그러나 A의 처리기 메서드는 public입니다. A는 구현하지 않은 코드에 대한 인터페이스로 사용되며 핸들러 메소드에 private 범위가 있으면 C가 클래스 A의 핸들러를 호출 할 수없는 경우 더 선호합니다. 그렇다면이 클래스를 어떻게 다시 디자인해야합니까? 감사! – akmer

0

당신은 패키지 오메가 패키지 알파와 C에서 A와 B를 넣을 수 있습니다 : 클래스 B와 C는 같은 찾고

package p.q; 

import p.q.B.BEvent; 
import x.y.z.C.CEvent; 
import x.y.z.C; 

public class A { 

// anonymous class implementing required interface 
private BListener myFacade = new BListener(){ 
    @Override 
    public void listen(BEvent event) { 
     bEventHappened(event);   
    }  
}; 

private B myB; 
private C myC; 

A() { 
    myC = new C(); 
    myB = new B(); 
    myB.registerListener(myFacade); 
} 

private void bEventHappened(BEvent theBEvent){ 
     myC.callWhenitHappens(myC.new CEvent()); 
} 
} 

. A와 B는 서로의 개인 회원 패키지에 액세스 할 수 있지만 C는 그렇지 않습니다. djna와 같은 인터페이스도 사용해야합니다.

package alpha ; 
public interface A { void doSomething () ; } 
public interface B { } 
class AImpl implements A { ... void doSomethingPrivate () { ... } } 
class BImpl implements B { AImpl a ; ... a.doSomethingPrivate () ; } 

package omega ; 
public interface C { public void handle (alpha.a a) ; ... } 
+0

동일한 패키지로 배치하면이 문제가 해결되지만 불행하게도 처음부터 코드를 작성하지 않으므로이 옵션이 없습니다.이 부분 (패키지)은 이미 있습니다. – akmer

1

여러 책임 인터페이스가있는 클래스가있는 것 같습니다. 이것은 나쁜 것입니다. 간단한 접근 방법은 익명 내부 클래스를 사용하여 콜백 인터페이스를 구현하는 것입니다.

+0

제안하시는 것의 작은 예를 들어 주시겠습니까? – akmer

0

당신은 그런 식으로이 작업을 수행 할 수 있습니다

interface EventSource<T>{ 
    void addEventListener(T listener); 
    void removeEventListener(T listener); 
} 
class B implements EventSource<SomethingListener> 
{ 
    A instA; 
    ... 
    public B(A instA) 
    { 
     this.instA = instA; 
     instA.installEventSource(this); 
     ... 
    } 
    ... 
} 
class A 
{ 
    ... 
    public void installEventSource(EventSource source) 
    { 
     source.addEventListener(listener); 
    } 
    public void uninstallEventSource(EventSource source) 
    { 
     source.removeEventListener(listener); 
    } 
} 
+0

그래서 클래스 A에서 클래스 B에 대한 참조가 있습니다. 이벤트가 발생하면 참조를 사용하여 해당 처리기를 호출합니다. 그러나 그 방법의 가시성은 무엇입니까? 그것이 공개이면 나는 여전히 같은 문제가 있습니다. 권리? – akmer

+0

'EventSource'는 클래스입니다. 플러그인 시스템 (OSGI 또는 Netbeans RCP)을 사용하여 플러그인을 숨기거나'internal' 패키지 아래에 배치 할 수 있습니다. 일반적인 규약은 모듈 외부에서 이러한 클래스를 사용하지 않는 것입니다. –

0

이 예를 들어 주셔서 감사합니다! 나는 분명하지 않다. 방법과 처리기가 많이 나는 약

public class Csystem() 
{ 

private AListener listener;//implements an event listener (the class C in my question) 

//methods here 
public void handleEventIncoming(Event e){ 
//Do some logic here 
    listener.raiseEvent(e); 
} 
public void handleEventOutgoing(Event e); etc 


} 

CSystem을 이야기하고있다 내가 가진 클래스 Csystem은 본질적으로 내 코드에 다른 구성 요소의 다른 개발자를위한 인터페이스입니다 클래스입니다. 다른 개발자는 AListener 클래스 (클래스 A)의 자체 버전을 작성하고 코드에 Csystem을 사용합니다. 이벤트가 어딘가에 발생할 때마다 클래스 B는 CSystem

의 이벤트 핸들러에 이벤트를 전달합니다 (예를 들어, 네트워크에 메시지가 도착)
public class Dispatch{ 
//This is class B 
private CSystem s; 

private void event_occured(Event e) 
{ 
    s.handleEventIncoming(e); 
} 
} 

} 

내 문제는 모두 (나에 의해 구현) 클래스 파견 및 클래스 AListener " "CSystem의 동일한 인터페이스를 참조하십시오. 나는 Alistener를 구현하는 개발자가 CSystem의 다른 뷰를보고 "볼"수 있고 공개 메서드 만 사용할 수 있기를 바랍니다. 나는 누군가가 실제로 사용할 수없는 방법을 (핸들러는 운영자 만이 사용하기에 의미가있는) 볼 수있는 좋은 생각이라고 생각하지 않는다. 이것을 달성하기위한 패턴이 있습니까?

+0

원본 질문을 편집 할 수 없어 여기에서 원래 질문의 세부 사항을 확장했습니다. 이렇게 돼서 미안하다! – Cratylus

관련 문제