Tell me more ×
Code Review Stack Exchange is a question and answer site for peer programmer code reviews. It's 100% free, no registration required.

I have written an implementation of the observer pattern that allows messages to be passed to listeners in what would normally be the notify() method. For example a subscriber sub-class might look like the pseudo-code below, where Message is a simple class that can be sub-classed and made to contain value objects or other data.

class MySubscriber extends Subscriber
{
    @Override
    public void notify( Message m )
    {
        if( m.getClass == MyMessage )
        {
            MyMessage myMessage = ( MyMessage ) m;
            if( myMessage.name == MyMessage.START )
            {
                // -- Finally do something here
            }
        }

        if( m.getClass == MyOtherMessage )
        {
            MyOtherMessage myOtherMessage = ( MyOtherMessage ) m;
            if( myOtherMessage.name == MyOtherMessage.INIT_SOMETHING )
            {
                // -- Finally do something else here
            }
        }

    }  
} 

Using conditionals like this to determine the message type seems a bit redundant and can get tedious in cases where a subscriber is listening for many message types. However, it is pretty explicit, easy to read and the implementation is quite simple. Is there a cleaner approach to achieve a similar result?

Btw, I attempted to add the tags: "observer" and "introspection" to this question but apparently I don't have enough points on this Stack Exchange site.

share|improve this question
You have some double checks: checking for type and the value of a string. I'd suggest using an enum and forget about the type checking, since everything appears to be a message instance. – Florian Salihovic Aug 20 '12 at 19:54
The parameter m could be a Message sub-class such as MyMessage or MyOtherMessage each with their own constants as is the case in the example. – jeremynealbrown Aug 20 '12 at 20:09
Yes, but that doesn't matter because the subclasses behave like Message instance. So, when you extract the constants in an enum class, you'd just had to speak against the Message type and could ignore the inheriting types. – Florian Salihovic Aug 21 '12 at 6:37
@Florian Salihovic - In some cases the message sub-classes might contain value objects or other properties not on the parent class. – jeremynealbrown Aug 21 '12 at 15:04

2 Answers

Personally I prefer polymorphism instead of conditions in such cases, as it helps to keep big conditions in a clean fashion - each condition in it's own class. As an example, in .NET they have generic event-handlers (subscribers) and following class system takes place (or something along these lines):

abstract class EventArgs { ... } // your abstract data class, Message if you will
class MyEventArgs : EventArgs { } // and it's implementation

abstract class EventHandler<T> // an abstract Subscriber
{ 
    public abstract Notify(T args); // Subscriber::notify() in your example
} 

class MyEventHandler : EventHandler<MyEventArgs>  // an implementation of a subscriber for one specific case, which would be MyEventArgs
{
    public Notify(MyEventArgs args) { ... }
}
share|improve this answer
I like this approach. It is definitely more elegant and should be doable in Java. – jeremynealbrown Aug 19 '12 at 18:10
Absolutely doable. Btw, you might also enjoy browsing through other types of refactoring. – Dmitriy Aug 19 '12 at 18:16

Just a couple of thoughts as it's hard to tell without more background:

  • Do you really want to use the == operator here, perhaps you should be using instanceof.

  • If the Subscriber needs to handle various types of messages why not include those types explicitly in theinterface? I think it makes it clear what the code sending the message intends, rather than funneling all messages through a single method. This may allow for compile time type checking.

  • Consider making a separate subscriber interface for each type of subscriber.

share|improve this answer
instanceof is a good tip. My goal is to write an abstract and reusable observer/listener like pattern and to avoid writing methods specifically for each message type. – jeremynealbrown Aug 20 '12 at 18:27
If you're having many types of messages perhaps your message interface isn't sufficient (not a complete interface). IMHO an interface should encapsulate all that is needed for two components to interact, otherwise you are forcing the message subscriber to think beyond the interface. – cyber-monk Aug 20 '12 at 20:46

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.