Java / Шаблоны для сокрытия методов от сторонних классов - PullRequest
0 голосов
/ 06 июля 2010

У меня есть класс A, у которого есть ряд обработчиков, например public void handleEv1 (), public void handleEv2 () и т. Д. Когда происходит событие, другой поток в классе B вызывает соответствующий обработчик из класса A (класс B имеетссылка на класс A (вид наблюдателя).При обработке события в соответствующем методе класса A, A в конечном итоге вызывает событие для EventListener (класс C, который я не создал).Мой вопрос заключается в следующем: есть ли шаблон, который я могу использовать, чтобы «скрыть» методы обработки класса A от классов, которые действуют как eventListeners (не реализован мной), и быть «видимым / доступным» только для класса B (которыйЯ реализую)?

Я редактирую свой оригинальный вопрос.У меня есть класс Csystem, в котором много методов и обработчиков, о которых я говорю

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 - это класс, который по сути является интерфейсом для других разработчиков других компонентов моего кода.Другой разработчик напишет свою собственную версию класса AListener (класс A) и использует Csystem в своем коде.Всякий раз, когда где-то происходит событие (например, поступило сообщение в сети), класс B передает событие обработчикам событий CSystem

public class Dispatch{
//This is class B
 private CSystem s;

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

}. Моя проблема в том, что и класс Dispatch (реализованный мной), и классAListener «видит» тот же интерфейс CSystem.Я хотел бы, чтобы разработчики, которые реализуют AListener, видели другое представление о CSystem и «видели» и могли использовать только общедоступные методы.Я не думаю, что это хорошая идея, чтобы увидеть методы, которые кто-то на самом деле не может использовать (обработчики имеют смысл использовать только диспетчер) Есть ли способ добиться этого?

Спасибо!

Ответы [ 5 ]

3 голосов
/ 06 июля 2010

Использовать интерфейсы.Отношения B с A возможны только через интерфейс, который B определяет и реализует.

Таким образом, с точки зрения B, он даже не импортирует A и не имеет доступа к определению A во время компиляции.

Отредактировано в ответ на вопрос.

Я полагаю, у вас есть класс C

ранее существовавший, неизменный вами, код в некотором пакете xy;

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

Мне кажется, что вы обеспокоены маловероятной проблемой.Зачем кому-то мешать создать объект А и делать это?Однако есть несколько возможностей:

1).Если A и B находятся в одном пакете, не делайте A и его метод общедоступным.Их должен видеть только B, поэтому в области действия пакета это будет работать.

2).Анонимный внутренний класс.Обратите внимание, что класс A ia не имеет открытых методов, поэтому C не может его использовать, и, тем не менее, B имеет открытые методы для анонимного внутреннего класса, который он может использовать.

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

Классы B и C выглядят следующим образом:

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
}

}

1 голос
/ 06 июля 2010

У вас, кажется, есть класс с интерфейсом с множеством обязанностей. Это плохо. Простой подход заключается в использовании анонимных внутренних классов для реализации интерфейсов обратного вызова.

0 голосов
/ 06 июля 2010

спасибо за ваш пример! Мне было не ясно, кажется. У меня есть класс Csystem, в котором много методов и обработчиков, о которых я говорю

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 - это класс, который по сути является интерфейсом для других разработчиков других компонентов моего кода. Другой разработчик напишет свою собственную версию класса AListener (класс A) и использует Csystem в своем коде. Всякий раз, когда событие где-то происходит (например, поступило сообщение в сети), класс B передает событие обработчикам событий в CSystem

public class Dispatch{
//This is class B
private CSystem s;

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

}

Моя проблема в том, что и класс Dispatch (реализованный мной), и класс AListener "видят" один и тот же интерфейс CSystem. Я хотел бы, чтобы разработчики, которые реализуют AListener, видели другое представление о CSystem и «видели» и могли использовать только общедоступные методы. Я не думаю, что это хорошая идея, чтобы увидеть методы, которые кто-то на самом деле не может использовать (обработчики имеют смысл использовать только диспетчер) Есть ли способ добиться этого?

0 голосов
/ 06 июля 2010

Вы можете сделать это так:

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 голосов
/ 06 июля 2010

Вы можете поместить A и B в пакет альфа и C в пакет омега.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 ) ; ... }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...