Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Where is the right place to register listeners

I'm working on a project that intensively uses the observer pattern. Many classes are used as event/message listeners. Usually, the listening class registers itself in the constructor, and I see a two problems with this:

  1. We are doing work in the constructor
  2. The class becomes dependent on the observed class even though it's only interested in the event itself.

should the registration be the responsibility of the listening class or should it be some place else?

like image 981
Nir Brachel Avatar asked Oct 19 '22 11:10

Nir Brachel


1 Answers

Subscribing from within a constructor can cause issues for inheritance. Say we have code which looks like this:

public class Parent {
    public Parent(EventObject source) {
        // initialize parent ...
        source.subscribe(this::someMethod);
    }
    public void someMethod() {
        ...
    }
...
}

public class Child extends Parent {
    public Child(EventObject source) {
        super(source);
        // initialize child ...
    }
...
}

The Child ctor calls the Parent ctor, which registers itself to the event source. Notice however that the Child object is not done initializing when the Parent is registered. If the event source updates before the Child ctor is finished, your code may behave very strangely.

A simple way to avoid this issue is to make subscriptions within factory methods, keeping ctors hidden.

public class Parent {
    public static Parent newInstance(EventObject source) {
        Parent p = new Parent();
        source.subscribe(p::someMethod);
        return p;
    }        
    protected Parent() {
        // initialize parent ...
    }
    public void someMethod() {
        ...
    }
...
}

public class Child extends Parent {
    public static Child newInstance(EventObject source) {
        Child c = new Child();
        source.subscribe(c::someMethod);
        return c;
    }    
    protected Child() {
        super();
        // initialize child ...
    }
...
}
like image 59
flakes Avatar answered Nov 15 '22 06:11

flakes