views:

136

answers:

5

Hi, I have a class A that has a series of handlers e.g. public void handleEv1(),public void handleEv2() etc. When an event occurs, another thread in class B, calls the correspondent handler from class A (class B has a reference to class A kind of observer-observable). In the handling of the event in the corresponding method of class A, A eventually raises an event to an eventListener (class C which is not created by me). My question is the following: is there a pattern I can use to "hide" the handling methods of class A from the classes that act as eventListeners (not implemented by me), and be "visible/accesible" only to class B (which I implement)?

I am editing my original question. I have class Csystem that has a lot of methods and the handlers I am talking about

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 is a class that is essentially an interface for other developers of other components to my code. Some other developer will write his own version of class AListener (class A) and use Csystem in his code. Whenever an event occurs somewhere (e.g. a message in the network arrived) class B will pass the event to the event handlers of CSystem

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

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

} My problem is that both class Dispatch (implemented by me) and class AListener "see" the same interface of CSystem. I would like the developers who implement the AListener to see a different view of CSystem and "see" and be able to use only methods that are public. I don't think that it is a good idea to see methods someone actually can not use (handlers are meaningful to be used only by dispatcher) Is there a pattern to achieve this?

Thank you!

+3  A: 

Use Interfaces. B's relationship with A is only via an Interface that B defines and A implements.

So from B's perspective, it doesn't even import A, or have access to the definition of A at compilation time.

Edited in response to question.

I beleive you have a class C

pre-existing, unchangable by you, code in some package x.y;

Class CEvent {
   // some event definition
};

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

--- code you write ---

package p.q;
public Class A implements BEventInterface {

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

}

And your concern is that anybody, even including C could call that bEventHappened() method.

My feeling is that you're concerned by an unlikely problem. Why would someone go to the trouble of creating an A object and doing that? However there are some possibilities:

1). If A and B are in the same package, do not make A and it's method public. Only B needs to see them, so at package scope this will just work.

2). Anonymous inner class. Note here that A ia class with a no public methods, so C can't use it and yet B has public methods on the anonymous inner class it can use.

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

With classes B and C looking like:

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

}

and

package x.y.z;

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

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

}

djna
Hi,You mean the following?public class B{ interface Handlers{ public void handleEv1(); public void handleEv1(); }etc}class A implements Handlers{ public void handleEv1(); public void handleEv1();etc}But with this design still aren't the handlers still accessible to C, since they are public? Or I misunderstand what you are saying?
akmer
But your A sends an Event to C, C doesn't know anything about A, it was compiled long before your A was written, there can be no code in C that knows about anA.myMethod().
djna
Thanks for the reply. The problem for me is the following(may be my thinking is wrong): I have class A which serves as a boundary between classes B and C. Class A has class C registered as a listener. Class B, when an event occurs, calls the handlerMethods of A and the method does some processing and raises the event to C. But the handler methods of A are public. A is used as an interface to code that I do not implement and would prefer if the handler methods had private scope so that C for example can not call a handler of class A. So How should I re-design my classes to achieve this? Thanks!
akmer
What does C look like now? I'll extend my answer to show what I expect to be the situation. However, maybe you have some different situation. So please extend your question with a bit more detail.
djna
A: 

You can put A and B in package alpha and C in package omega. A and B have access to each other's package private members, but C does not. You should also use interfaces like djna said.

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 ) ; ... }
emory
Placing is the same package solves this but unfortunately I do not have this option since I am not starting to code from scratch and this part (packages) is already there
akmer
+1  A: 

You appear to have a class with an interface with multiple responsibilities. This is a bad thing. A simple approach is to use anonymous inner classes to implement callback interfaces.

Tom Hawtin - tackline
Could you please give a small example of what you are suggesting?
akmer
A: 

You can do this like that:

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);
    }
}
Ha
So in class A, I have reference to class B. When the event occurs, I will use the reference to call the corresponding handler. But what is the visibility of that method? If it is public then I still have the same problem. Right?
akmer
`EventSource` is a class. You can hide it using plugin systems (OSGI or Netbeans RCP) or just place it under `internal` package - a common convention is not to use such classes outside of the module.
Ha
A: 

Hi djna, thank you for your example! I was not clear it seems. I have class Csystem that has a lot of methods and the handlers I am talking about

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 is a class that is essentially an interface for other developers of other components to my code. Some other developer will write his own version of class AListener (class A) and use Csystem in his code. Whenever an event occurs somewhere (e.g. a message in the network arrived) class B will pass the event to the event handlers of CSystem

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

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

}

My problem is that both class Dispatch (implemented by me) and class AListener "see" the same interface of CSystem. I would like the developers who implement the AListener to see a different view of CSystem and "see" and be able to use only methods that are public. I don't think that it is a good idea to see methods someone actually can not use (handlers are meaningful to be used only by dispatcher) Is there a pattern to achieve this?

I could not edit my original question so I expanded on details of my original question here. Sorry for this!