Unravel โบ Java concepts โบ Design patterns and architecture
Observer and event listeners
In the observer pattern an object (the subject) keeps a list of listeners and tells all of them when something happens.
Learn these first
At a glance
A newsletter: readers subscribe once, the publisher sends each issue to everyone on the list, and neither side needs to know more about the other than "subscribe" and "here is the news".
- 1The subject has addListener(l), removeListener(l) and a fire(event) method that loops over the listeners and calls each oneListeners implement a small interface, often a functional interface so a lambda works.
- 2Listener registration is a loose coupling: the publisher does not know who reacts, so you can add features (audit log, cache invalidation) without touching it
- 3JDK examples: PropertyChangeSupport, Swing listeners, Flow.PublisherSpring: ApplicationEventPublisher and @EventListener. Messaging systems are the distributed version.
- Always unregister listeners that outlive the object that registered them, or the subject keeps them alive (a classic memory leak)
- Decide what happens when a listener throws: one failing listener should not stop the rest, so catch and log around each call
- Nothing is magic here: the subject holds references to the listener objects and calls an interface method on each
import java.util.*;import java.util.concurrent.CopyOnWriteArrayList;public class Thermostat { interface Listener { void onChange(double celsius); } private final List<Listener> listeners = new CopyOnWriteArrayList<>(); public void addListener(Listener l) { listeners.add(l); } public void removeListener(Listener l) { listeners.remove(l); } public void set(double celsius) { for (Listener l : listeners) { try { l.onChange(celsius); } catch (RuntimeException e) { System.err.println("listener failed: " + e); } } }}- line 6 uses addListener, the core of Observer and event listeners
- line 7 uses removeListener, the core of Observer and event listeners
Read the full explanation (about 1 min)
In the observer pattern an object (the subject) keeps a list of listeners and tells all of them when something happens. Button clicks, property changes and Spring events all work this way.
A mental model
A newsletter: readers subscribe once, the publisher sends each issue to everyone on the list, and neither side needs to know more about the other than "subscribe" and "here is the news".
How it works
The subject has addListener(l), removeListener(l) and a fire(event) method that loops over the listeners and calls each one. Listeners implement a small interface, often a functional interface so a lambda works.
Listener registration is a loose coupling: the publisher does not know who reacts, so you can add features (audit log, cache invalidation) without touching it.
JDK examples: PropertyChangeSupport, Swing listeners, Flow.Publisher. Spring: ApplicationEventPublisher and @EventListener. Messaging systems are the distributed version.
Going deeper
Always unregister listeners that outlive the object that registered them, or the subject keeps them alive (a classic memory leak). A CopyOnWriteArrayList of listeners makes firing safe while listeners add or remove themselves.
Decide what happens when a listener throws: one failing listener should not stop the rest, so catch and log around each call.
Callbacks run on the thread that fires the event; a slow or blocking listener delays everything. Dispatch to an executor if needed.
Under the hood
Nothing is magic here: the subject holds references to the listener objects and calls an interface method on each. java.util.Observable is deprecated since Java 9 in favour of PropertyChangeListener and reactive streams.
Common mistakes
- Never removing listeners.
- Modifying the listener list while iterating it.
- Letting a listener exception break the loop.
- Slow work on the firing thread.
How Unravel recognises it
When you paste code, Unravel looks for these signs of observer and event listeners. Spotting them yourself is a good habit when you read unfamiliar code:
- Types:
ObserverObservablePropertyChangeListenerPropertyChangeSupportEventListener - Method calls:
addListener()removeListener()addObserver()notifyObservers() - Method names you declare:
addListener()notifyListeners()subscribe()fireEvent()
Part of a learning path
- Design patterns and SOLID ยท previous: Strategy pattern ยท next: Decorator and wrapper classes
Related concepts
Frequently asked questions
What is Observer and event listeners?
In the observer pattern an object (the subject) keeps a list of listeners and tells all of them when something happens. Button clicks, property changes and Spring events all work this way.
What are the most common mistakes with Observer and event listeners?
Never removing listeners. Modifying the listener list while iterating it. Letting a listener exception break the loop. Slow work on the firing thread.
How can I see Observer and event listeners in real code?
Paste your own Java into Unravel and it will point out where observer and event listeners appears, explain how it works at the detail level you choose, and draw the flow of the code around it.