0

I'm writing a Java program with a custom event manager, which is of course the observer pattern. Should the calls to add event listeners/handlers be in the classes that listens/handles the events such as in their constructor, or outside them such as near the code that calls their constructor?

For example, say there's a class that creates a new user and raises an event that a new user has been created. Should the class that sends welcome emails to new users register itself as an event handler, perhaps in its constructor? Or, should that registration not happen within the class that will handle the event?

I'll point out there are situations where instances of a class need to handle separate events. For example, a class handling UI button clicks that registered itself in its constructor would need to be given the event in its constructor to know which to listen to.

It seems like having the class register itself violates the single responsibility principle. It also forces some coupling for the class to know the events it needs to respond to, especially when there's multiple similar events that all get handled the same way. When more similar events are added, it forces the class registering itself to be changed. Of course, registering outside the class forces those changes also, but it's at least not within that class.

However, I don't love the idea of registering listeners to events outside the classes handling the events, because that seems to make it more likely the registration could be forgotten.

1 Answer 1

1

Should the calls to add event listeners/handlers be in the classes that listens/handles the events such as in their constructor, or outside them such as near the code that calls their constructor?

Both are valid approaches in the right context. It very much depends on whether a given handler can have different configurations. If yes, external configuration (or sufficient parametrization) is warranted. If no, internal configuration seems perfectly adequate.

It seems like having the class register itself violates the single responsibility principle.

I disagree. Conceptually, registering to and observing an event listener is a form of dependency subscription; and it is a class' responsibility to declare the dependencies it requires. This is no different from a class interacting with e.g. the factory you passed in as a dependency.

Declaring your dependencies is not considered part of the responsibility of the class (in terms of SRP), it's just some meta-configuration that is logically required for any system with integrated components.

It also forces some coupling for the class to know the events it needs to respond to, especially when there's multiple similar events that all get handled the same way

Events are a form of public interface. It is expected for a class to know the interface of its dependency so that it can interact with it.

When more similar events are added, it forces the class registering itself to be changed.

When the public contract of any dependency changes, having to make adjustments in the consumers of that dependency is always a possibility.

However, I don't love the idea of registering listeners to events outside the classes handling the events, because that seems to make it more likely the registration could be forgotten.

"It could be forgotten" should not be the driving decider here. It could be forgotten internally too.

The question is more whether there is more than one possible configuration. If there is, then external configuration makes the most sense so that each use case can define its own configuration. This could be wrapped using composition, inheritance, or even just explicitly defined by the consumer itself.

If there is only on configuration specific to that handler, then internal configuration makes the most sense, as that one specific configuration requires no variability and should always be used in conjunction with the handler anyway.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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