I'm coming to Java from C# where events are first class citizens and event handlers can be private methods. I'm now working on a Java project where I of course need to use an Observer pattern to implement eventing.
Since the Observer needs to expose its listener/handler callback methods to the Observable class, it seems that this is exposing implementation of the details of the Observer to other unconcerned classes. I can set the access to these methods to the package level which would keep these implementation details hidden to consumers of my package, but it still has a bad "smell" to me.
Is this just something I need to grit my teeth and bare or is there a better way?
With the Observer pattern your classes which are observing do not need to expose their implementations. Often your class which is notifying other classes will have its own associated interface for those other classes to implement.
public interface Observer
{
public void handleSomeEvent(Object someObjectOfImportance);
}
public class Observable
{
public void register(Observer observer);
}
Any class can implement the Observer
interface and register itself without exposing any implementation details. It does expose that it implements an interface, but that does not specify how it implements it. Alternatively, you could provide an anonymous implementation.
public class SomeObserverImplementation implements Observer
{
public void handleSomeEvent(Object someObjectOfImportance)
{
// I can do whatever I want here
}
}
Update If you are concerned that your class now is exposing a new interface there are some ways to work around it. One is to create an anonymous implementation. Another is that you can have a private internal class which implements the Observable interface.
public class IDontWantOthersToKnowIObserve
{
private class HiddenObserver implements Observer
{
public void handleSomeEvent(Object someObjectOfImportance)
{
...
}
}
... in some method ...
theObservable.register(myHiddenObserver);
}
To use an anonymous implementation:
theObservable.register(new Observer()
{
public void handleSomeEvent(Object someObjectOfImportance)
{
// ...
}
});
In Java this is normally not thought of as really exposing implementation details, however, if you really want to hide the functionality of your class from other classes then you need to have your class implement different interfaces that each only expose a subset of the overall class functionality. If you then ensure that other classes only access your class through a particular interface (possibly via a factory) then you effectively hide your implementation.
E.g:
public interface Observer<T>
{
public void notify(T event);
}
public interface PublicFace
{
public void doSomething();
}
public class SomeClass implements Observer<Event>, PublicFace
{
public void notify(Event event)
{
// ...
}
public void doSomething()
{
// ...
}
}
public class FaceFactory
{
public static PublicFace getPublicFaceInstance()
{
return new SomeClass();
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With