Java Generic Observer

Design patterns, you gotta love them! What would we do without our beloved Observer Pattern? Since its usage is so common, most frameworks provide an implementation out of the box. Microsoft even added a language construct for it to C#, called ‘events‘. As a Java developer, it would seem you are less lucky. Through the years, my unconditional trust in the design of frameworks has been wavering. Java’s default implementation of the Observer pattern is a nice example of what I consider bad design. Perhaps that’s why it’s not even used in the framework itself. (ActionListener in awt)

If you haven’t watched “Despicable Me” yet, stop reading and watch it first! ;) It’s a great movie. Consider a person (Gru) needing the ability to watch over his minions.

A standard implementation using the framework’s classes would be:

Gru gru = new Gru();
Minion fred = new Minion();
fred.addObserver(gru);
fred.moo();

public class Minion extends Observable
{
    public void moo()
    {
        setChanged();
        notifyObservers("hehehe");
    }
}

public class Gru implements Observer
{
    public void punch(Minion minion) { ... }

    @Override
    public void update(Observable o, Object arg)
    {
        if (o instanceof Minion)
        {
            String s = (String)arg;
            if (s.equals("hehehe"))
            {
                punch((Minion)o);
            }
        }
    }
}

The thing that bothers me (and others) in this implementation is the need for type checking. After browsing around, I found an implementation by Allain Lalonde who addressed this issue by using a dynamic proxy. I found his solution to be really useful, implemented it, and added a small feature which allows extending from a generic AbstractObservable<T> class. The result looks as follows:

Gru gru = new Gru();
Minion fred = new Minion();
fred.addObserver(gru);
fred.moo();

public interface IMinionListener
{
    public void laughing(Minion minion);
}

public class Minion extends AbstractObservable<IMinionListener>
{
    public void moo()
    {
        getEventDispatcher().laughing(this);
    }
}

public class Gru implements IMinionListener
{
    public void punch(Minion minion) { ... }

    public void laughing(Minion minion)
    {
        punch(minion);
    }
}

How it works.

Events are dispatched through an ObserverPool as described by Allain Lalonde. This is a proxy class which forwards calls (as defined by the interface) to a set of listeners, the observers. You can use this pool directly, or extend from AbstractObservable which already creates and wraps it for you.

Possible problems.

As with the original Observable, you might not be able to extend from AbstractObservable since multiple inheritance isn’t allowed. You could use composition instead, and use the IAbstractObservable interface.

AbstractObservable source code

Better solution? (most likely)

I wrote this code a while ago, before I started this blog. While writing, I followed a link on Wikipedia which I wish I found before. It seems there is a free package available called PerfectJPattern, containing componentized design patterns, including the observer pattern. From the looks of it, they also use a proxy approach. The project looks really well maintained, clean, and thoroughly implemented. Next time I develop in Java, I’ll check it out.

About these ads
  1. #1 by Allain on February 3, 2011 - 5:28 am

    You managed to figure out how to get the class of the generic class, which is something I could never do.

    Nice work. I’m impressed.

  1. Null Checks for Event Handlers, an Aspect Solution « Whathecode

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: