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:
should the registration be the responsibility of the listening class or should it be some place else?
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 ...
}
...
}