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.
Related
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.
in the reference book "Design Patterns Elements of Reusable Object-Oriented Software" by the gang of four, the intent of the visitor pattern is explained as follow :
Represent an operation to be performed on the elements of an object structure. Visitor lets you define a new operation without changing the classes of the elements on which it operates.
Another advantage I read about the visitor pattern is that:
ADD A NEW OPERATION WITHOUT HAVING THE SOURCE CODE OF THE CLASSES..
I made a deep search in Google, but I did not find any example showing how to do that.
So let's take a simple example :
public interface MyInterface {
public void myMethod();
}
public class MyClassA implements MyInterface {
/* (non-Javadoc)
* #see com.mycomp.tutorials.designpattern.behavorials.MyInterface#myMethodA()
*/
public void myMethod() {
System.out.println("myMethodA implemented in MyClassA");
}
}
public class MyClassB implements MyInterface {
/* (non-Javadoc)
* #see com.mycomp.tutorials.designpattern.behavorials.MyInterface#myMethodA()
*/
public void myMethod() {
System.out.println("myMethod implemented in MyClassB");
}
}
So how would I add a new method myNewMethod() to this hierarchy of classes without changing them, using the visitor pattern?
You example is not a visitor pattern. It is just inheritance.
A visitor pattern first requires an visitor interface
interface ThingVisitor {
void visit(ThingA a);
void visit(ThingB b);
}
Now you need an interface Thing:
interface Thing {
void accept(ThingVisitor visitor);
}
And your implementation of, for example, ThingA would be
class ThingA implements Thing {
public void accept(final ThingVisitor visitor) {
visitor.visit(this);
}
}
Now you see the logic to handle the Thing types is contained in the implementations of ThingVisitor.
Let's say you have a Message class, and 2 subclasses Email and Sms.
You could have many operations on these two classes, like sendToOnePerson(), sendToSeveralPeople(). But you probably don't want to have these methods in the Email and Sms class directly, because it tightly couples them to the SMTP/phone system. And you would also like to be able to add other operations in the futre, like forward() or delete(), or whatever. So the first implementation you could use is
public void delete(Message message) {
if (message instanceof Email) {
deleteEmail(Email) message);
}
else if (message instanceof Sms) {
deleteSms((Sms) message);
}
}
But this is ugly: it's not object-oriented, and it will fail if there is a new VoiceMessage subclass appearing.
An alternative is to use the visitor pattern.
public interface MessageVisitor {
void visitEmail(Email email);
void visitSms(Sms sms);
}
public abstract class Message {
public void accept(MessageVisitor visitor);
}
public class Email extends Message {
#Override
public void accept(MessageVisitor visitor) {
visitor.visitEmail(this);
}
}
public class Sms extends Message {
#Override
public void accept(MessageVisitor visitor) {
visitor.visitSms(this);
}
}
This way, to implement send(), all you need is a MessageVisitor implementation that can send an email and send an Sms:
SendMessageVisitor visitor = new SendMessageVisitor();
message.accept(visitor);
And if you introduce a new delete() operation, you don't have to touch to Message classes at all. All you need is a DeleteMessageVisitor:
DeleteMessageVisitor visitor = new DeleteMessageVisitor();
message.accept(visitor);
So, basically, it's a bit like if you added polymorphic methods to the Message classes by not actually modifying the Message classes.
The visitor pattern assumes that you have a method in the classes you want to "visit" which accepts and executes the visitor, here is an example. The pattern is not motivated by adding functionality to foreign classes but to localize functionality in the visitors which would otherwise be spread over several classes, e.g. for saving elements (see the example).
Quick description of the visitor pattern.
The classes that require modification must all implement the 'accept' method. Clients call this accept method to perform some new action on that family of classes thereby extending their functionality. Clients are able to use this one accept method to perform a wide range of new actions by passing in a different visitor class for each specific action. A visitor class contains multiple overridden visit methods defining how to achieve that same specific action for every class within the family. These visit methods get passed an instance on which to work
I had an idea and it goes like this:
Parse a file on service side.
Create a list of actions based on the file's contents.
Pass the list of actions to the client side.
Have the client define and perform actions based on the items on the list.
As in the visitor pattern, we'd have a class for the actions and all of them inherit the Action interface. The clients would then implement the visitors. In Java it'd be something like this:
public interface Action {
void act(Visitor visitor);
}
public class PerfectAction implements Action {
void act(Visitor visitor) {
visitor.bePerfect();
}
}
public class VisibleAction implements Action {
void act(Visitor visitor) {
visitor.beVisible();
}
}
public interface Visitor {
void bePerfect();
void beVisible();
}
The Problem
I can't create Proxy classes for the Action and Visitor interfaces. They do not contain setters and/or getters. Plus they do not contain any data. Is it possible to pass this knowledge of which method should be called on the Visitor object from service to client side?
Request Factory can only move data around (EntityProxy and/or ValueProxy), and ask the server to do things on behalf of the client (RequestContext).
To transfer actions, the client and server first need to share the knowledge of those actions that can be performed.
You then have two solutions:
move to GWT-RPC
because the client has to know every possible action upfront anyway, create an enum or whatever to identify each action, and transfer those identifiers to the client, which will map them back to concrete actions to perform.
I don't think this is how you'd implement the visitor pattern. I'd do something like this
public interface ActionVisitor {
void visit(VisibleAction va);
void visit(PerfrectAction pa);
}
public class PerfectAction implements Action {
void act(Visitor visitor) {
visitor.visit(this);
}
}
public class VisibleAction implements Action {
void act(Visitor visitor) {
visitor.visit(this);
}
}
Then I'd define an implementation of the visitor that performed the appropriate actions.
It's important to define it in this way so that the logic of what the visitor does is external to the class. Prior to this, each implementation had a different implementation of the visitor, so it'd be harder to change behaviour.
I think that this will solve your problem, because now the logic of what to do is externalized to the visitor.
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
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.