I have a class MyObserver that listens to changes in Notifier. Notifier extends Observable and notify its events with notifyObservers(Object). The object passed as argument is always an instance of the same class. The problem is that each observer need to listen to diferent events. For example one observer needs to listen to state changed events and others to all types of events. How can I do this with observer pattern?
Thanks.
Use notifyObservers(Object arg) version and create some sort of "event type" object to stick in there. In your observing classes simply filter on the passed in event class.
public void update(Object observable, Object arg) {
if ( (MyEvent) arg.isEventX() ) { /* do stuff */ }
}
I think that the Java built-in implementation of the Observer Pattern is not suitable for your case.
In fact, the general Observer pattern is usable when just one Observable kind of events can arise. In the Observer Design Pattern, all the Observes get notified always.
So, in this case, you need to extend the general Observer pattern, by defining your own Observable interface, for example, this way:
public enum EventKind {
EVENT_A, EVENT_B, EVENT_C;
}
public interface Observable {
public void registerObserver(EventKind eventKind);
public void unregisterObserver(EventKind eventKind);
public void notifyObservers(EventKind eventKind);
}
Then you can just implement this Observable interface with internal lists for each kind of event to notify. You can still use the Java built-in Observer interface if you wish.
This approach has the following benefits:
You can flexibly add more kind of events
without affecting the code of the
Observers.
You can register any observer to any
event.
You update just the Observers
that are effectively interested in
each event.
You avoid "empty methods", "event type checking" and other
tricks on the Observers side.
If you can change the design a bit:
interface MyObserver {
public void stateChangeEvent();
public void otherEvent();
}
class MyObserverAdapter implements MyObserver {
public void stateChangeEvent() {
// some default implementation or no implementation.
}
public void otherEvent() {
// some default implementation or no implementation.
}
}
class MyStateChangeObserver extends MyObserverAdapter {
public void stateChangeEvent() {
// implement behavior specific to this class.
}
}
class MyOtherObserver extends MyObserverAdapter {
public void otherEvent() {
// implement behavior specific to this class.
}
}
Usage:
MyObserver stateObserver = new MyStateChangeObserver();
MyObserver otherObserver = new MyOtherObserver();
notifier.notifyObservers(stateObserver);
notifier.notifyObservers(otherObserver);
You can test for a state change by doing the following in the Observable class:
public void update(Observable o, Object arg)
{
if(o.hasChanged())
{
// do something
}
}
The observers that listen to anything don't need this test. This is probably the easiest way if you only want to listen for state changes.
Related
Question
I'm having trouble understanding the following UML-diagram of the Observer pattern from the "Elements of Reusable Object-Oriented Software". Could anyone explain me why my Java implementation is wrong and what I have to change to implement it correctly?
UML-Diagram
Attempted (but wrong) implementation
public interface Subject {
public static final List<Observer> observers = new ArrayList<Observer>();
public void attach(Observer o);
public void detach(Observer o);
public void notifyObservers();
}
public interface Observer {
public void update();
}
public class ConcreteSubject implements Subject {
private String subjectState;
#Override
public void attach(Observer o) {
observers.add(o);
}
#Override
public void detach(Observer o) {
observers.remove(o);
}
#Override
public void notifyObservers() {
for (Observer o : observers) {
o.update();
}
}
public String getState() {
return subjectState;
}
public void setState() {
subjectState += "x";
}
}
public class ConcreteObserver implements Observer {
private ConcreteSubject subject;
public String observerState;
#Override
public void update() {
observerState = subject.getState();
}
}
One problem is that you have a static list of observers in Subject so all subjects share the same observers. However, the pattern requires that each individual subject has its own observers so put the list into ConcreteSubject and make it an instance field.
Another problem is that your ConcreteObserver has a field of type ConcreteSubject. It should, however, not know about the concrete implementation of Subject so the field should only have the type Subject.
Edit: Actually the UML diagram requires the concrete observer to know about the concrete subject in order to be able to call getState() so the above paragraph is not true in your case - this should not be a problem here.
However, in reality I would actually have another interface that extends Subject and hides the implementation of ConcreteSubject from the observer.
Edit 2:
As has been suggested you could also use an abstract class to handle the observers of a subject. That could be a class in between Subject and ConcreteSubject or even Subject itself but since Java doesn't support multiple inheritance I'd often use some other approach and make Subject just an interface.
The easiest implementation would then be to have ConcreteSubject maintain the list of observers but in a real world application you'd not want to have developers do that or rely on them implementing it correctly.
Instead you could use a central registry that maintains the list of observers for each subject and which the subject uses to inform its observers. Many dependency injection frameworks out there operate in a way like that, i.e. whenever a "subject" changes they will inform its observers about that event.
I'm setting up an event system, and I want all my events to extend the Event class I've created. However, I also want to at any point be able to add in an additional setCanceled and isCanceled methods.
Here's an example:
public class Event {}
public interface EventCancelable {
public default void setCanceled(boolean canceled) {...}
public default boolean isCanceled() {...}
}
public class PlayerEvent extends Event {
public Player player;
public PlayerEvent(Player player) {
this.player = player;
}
}
public class PlayerMovementEvent extends PlayerEvent implements EventCancelable {...}
As you can see, I used an interface to add in the methods later.
The problem is how I have to store if an event is canceled:
public interface EventCancelable {
Map<Object, Boolean> canceled = new HashMap<>();
public void setCanceled(boolean canceled) {
canceled.put(this, canceled);
}
public boolean isCanceled() {
return canceled.get(this);
}
}
Notice since Java only allows static fields, I have to create a map to store which events are canceled. This works fine, but after a while, this will take up more and more memory considering events are being called very frequently. Is there a way to add in cancelable features without using an interface, and without manually putting the code into every event I want to be able to cancel? I can't use an EventCancelable class, since then the PlayerMovementEvent wouldn't be able to extend PlayerEvent and EventCancelable at the same time, since I don't want all PlayerEvents to be cancelable.
Or is Java smart enough to empty the map of extra events no longer used since the map is only used in the interface with this added as the argument?
You could try to use a WeakHashMap, look for an extended example here.
But, you should know there are caveats:
you have zero control or knowledge when dead entries will be removed from the Map
this puts additional pressure on the GC, as it needs to do additional work for these types of references (WeakReference under the hood of WeakHashMap)
Default methods are not meant to be used like that. They should provide implementations of methods which can have sensible defaults implemented using the other public methods of the interface.
Try composing classes:
interface Cancellable {
void cancel();
boolean isCancelled();
}
class CancellableImpl implements Cancellable {
private boolean cancelled;
...
}
class PlayerMovementEvent extends PlayerEvent implements Cancellable {
private CancellableImpl cancellable = new Cancellable();
public cancel() { cancellable.cancel(); }
public isCancelled() { return cancellable.isCancelled(); }
...
}
Only a few extra lines, but it makes things much easier to understand.
I want to avoid the using of instanceof:
here is my case :
The definition of my Events classes are in a commons module :
public class Event1 extends AbstractEvent{
}
public class Event2 extends AbstractEvent{
}
public class Event3 extends AbstractEvent{
}
in another module called jms i have a listener that receive Event message from a queue :
public class MyMessageListener implements MessageListener {
#Override
public void onMessage(Message message) {
// CONVERT message to Event Object
if (event instanceof Event1) {
// Execute Processing 1
}
if (event instanceof Event2) {
// Execute Processing 2
}
if (event instanceof Event3) {
// Execute Processing 3
}
}
I want to avoid using instanceof and the best things for doing this is the visitor pattern with an execute method in the AbstractEvent and every leaf classes will implement it .
My problem is that in the common package i don't have access to the classes responsible for the processing . theses classes exist only in the jms module .
Is there any Tips or hint to do this (Advanced Visitor) or another pattern to do that
Put all possible behaviours to Map<Class, Runnable> and match event's type and Runnable type.
In such cases, the visitor Pattern can sometimes help. The visitor pattern is mainly suitable if your class hierarchy doesn't change much, because for each change in the class hierarchy you also must change the visitor (but that is also the case if you're using `instanceof').
To use the visitor pattern, you need to define a Visitor interface which contains a visit method for all types you want to visit:
interface Visitor {
visit(Event1 event);
visit(Event2 event);
visit(Event3 event);
}
first you want a common superclass which is the root for all classes you want to apply the visitor to. This superclass contains a method callVisitor:
public abstract class MyEvent extends AbstractEvent {
public abstract void visit(Visitor v);
}
public class Event1 extends MyEvent{
public void visit(Visitor v) {
v.visit(this); // calls visit(Event1)
}
}
public class Event2 extends MyEvent{
public void visit(Visitor v) {
v.visit(this); // calls visit(Event2)
}
}
public class Event3 extends MyEvent{
public void visit(Visitor v) {
v.visit(this); // calls visit(Event3)
}
}
Finally, you can create a visitor instance every time you need different behaviour based on the runtime type of the class:
public void onMessage(Message message) {
Visitor v = new Visitor() {
public void visit(Event1 event) {
// Execute Processing 1
}
public void visit(Event2 event) {
// Execute Processing 2
}
public void visit(Event3 event) {
// Execute Processing 3
}
}
event.visit(v);
}
The visitor pattern might be overkill in your situation, but I find it useful sometimes. The major advantage over using instanceof and other possible solutions is that it is typesafe: if you add a class to the hierarchy, the project will not compile until you added a visitor method to all visitors you defined.
As an alternative approach to the other answers, you could move the decision logic into your messaging configuration, so that each type of event is consumed by a MessageListener dedicated to processing only one type of Event. This will remove any "if" logic from your Consumer.
A caveat to this approach is that multiple consumers may process the events out of order. If this is an issue for your problem domain you may not wish to deal with the out-of-sequence issues yourself.
See JMS Selectors for more information
The advantages to this approach are:
Consumers are responsible for only one Event type (simplification)
You can add more Consumers independently based on event type (scalability)
You could have the AbstractEvent declare an abstract isOfType() method:
public abstract class AbstractEvent {
public abstract boolean isOfType( String type );
}
It would eliminate the instanceof's but not the if switching, though...
Cheers,
What should be the preferable Java interface or similar pattern that could be used as a generic callback mechanism?
For example it could be something like
public interface GenericCallback
{
public String getID();
public void callback(Object notification);
// or public void callback(String id, Object notification);
}
The ID would be needed for cases of overriden hashCode() methods so that the callee identifies the caller.
A pattern like the above is useful for objects that needs to report back to the class they were spawned from a condition (e.g., end of processing).
In this scenario, the "parent" class would use the getID() method of each of these GenericCallback objects to keep a track of them in a Map<String, GenericCallable> and add or remove them according to the notification received.
Also, how should such an interface be actually named?
Many people seem to prefer the Java Observer pattern, but the Observable class defined there is not convenient, since it not an interface to circumvent single inheritance and it carries more functionality than actually needed in the above, simple scenario.
I would genericize the callback, based upon the type of Object passed. This is particularly useful for EventListeners listening for different classes of events. e.g.
public interface Callback<T> {
public void callback(T t);
}
You may be able to use the type T as the key in a Map. Of course, if you want to differentiate between two callbacks that take the same argument, like a String, then you'd need something like your getID().
Here my old blog about using this for Event Listeners The interface Events.Listener corresponds to Callback<T> above. And Broadcasters uses a Map to keep track of multiple listeners based upon the class they accept as the argument.
I'd recommend using Observer pattern since the Observer pattern is the gold standard in decoupling - the separation of objects that depend on each other.
But I'd recommend avoiding using the Java.util.Observable class if you are looking for a generic callback mechanism. Because Observable has a couple of weaknesses: it's not an interface, and forces you to use Object to represent events.
You can define your own event listener like this:
public class MyEvent extends EventObject {
public MyEvent(Object source) {
super(source);
}
}
public interface MyEventListener {
void handleEvent(EventObject event);
}
public class MyEventSource {
private final List<MyEventListener> listeners;
public MyEventSource() {
listeners = new CopyOnWriteArrayList<MyEventListener>();
}
public void addMyEventListener(MyEventListener listener) {
listeners.add(listener);
}
public void removeMyEventListener(MyEventListener listener) {
listeners.remove(listener);
}
void fireEvent() {
MyEvent event = new MyEvent(this);
for (MyEventListener listener : listeners) {
listener.handleEvent(event);
}
}
}
looks like you want to implement the Observer pattern. In this url is a complete implementation for the observer pattern in Java. In your case the observer will be the callback.
Also If you need to implement something more complex, you will end up doing an event/notifier pattern. Take a look at this other pattern here.
Thanks,
#leo.
Callbacks in Java8 can now be done with the java.util.function package.
See Java 8 lambda Void argument for more information.
I am implementing the Observer / Observable pattern using Java. However, I am encountering a problem in the Observer portion of my code.
Observable
public class Model extends Observable {
public void notify() {
this.setChanged();
this.notifyObservers(new ArrayList<A>());
this.notifyObservers(new ArrayList<B>());
}
}
Observer
public class View implements Observer {
#Override
public void update(Observable observable, Object object) {
// TODO: If object is ArrayList<A>?
System.out.println("A");
// TODO: If object is ArrayList<B>?
System.out.println("B");
}
}
How would I fill in the TODO comments to check for the generic on the ArrayList? Is this even possible? (I would prefer to do it without implementing more classes, if possible.)
An Observable should send one and only one type of data.
public class ModelA extends Observable {
public void notify() {
this.setChanged();
this.notifyObservers(new ArrayList<A>());
}
}
public class ModelB extends Observable {
public void notify() {
this.setChanged();
this.notifyObservers(new ArrayList<B>());
}
}
Your other alternative is to put ArrayList<A> and ArrayList<B> into a class. You can notify your observers with that class.
You could use instanceof to see what type is your object but you are misusing the pattern.
The idea is that the Observable has a well defined interface and all the Observer needs to know is to use the API to pass the notification.
Logic to know what exactly is the Observable should not be mixed in the code.
From your question sounds to me you have 2 Observable and they should keep their own listeners interested specifically in them for notification. Not one combined