Observer Pattern in RxJava
One of my previous posts about back pressure mentions a concept of an Observable without providing many details. This post is a deeper dive into how the Observer pattern is applied in the world of reactive programming.
Observer Pattern: Pros and Cons
First off, let’s have a look at the Observer Pattern to see what problem does it solve and what limitations there are.
The pattern allows for efficient event handling, because it decouples listeners from the observed events.
Key characteristics:
- Loose coupling between the observed Subject and Observers
- Observers (listeners) act on (update) notifications about a state change (event)
- Observers can be dynamically added and removed
Challenges:
- Events are treated in isolation. It’s hard to relate to a stream of events in time (grouping, queries)
- Completion cannot be signalled. Chances are resources won’t get freed up, which can lead to memory leaks.
- No framework to deal with concurrency.
Reactive Observer
Rx expands upon the Observer pattern and adds new features.
I hope the picture speaks for itself. In a nutshell:
- Subscription provides a means for an Observer to unsubscribe
- Observable is able to signal completion (think a finite sequence of events – reading file contents etc.)
- Error handling
I could go and throw in an example implementing the pattern by using Observer and Observable. In fact, implementing your own observers / subscribers is seen as error prone and unnecessary.
There are good few examples in my previous post about back pressure, or another one – counting words in a file, where I do indeed implement a custom subscriber.
As a library, RxJava provides a variety of Observable and Observer implementations allowing for a high level of parallelism and built-in concurrency.
Summary
- It is not always necessary or desired to know the exact implementation of an Observer. Leverage overloads of Observable.subscribe and focus on your stream processing pipeline.
- Rx goes beyond the conventional Observer pattern. It provides a special type Subject, a hybrid between an Observable and an Observer. This lets you further streamline the pipeline and cache or buffer data.
- It is important to understand Observable Contract. Being mindful of the protocol helps avoid pitfalls. For instance, no new events are emitted, once processing completes (onError, onCompleted). Not all rules are obvious from the API. For example, back pressure is optional – adjust your assumptions about what the library can do for you by default.
Thanks for reading to the end. Please let me know your questions and experience regarding reactive programming in the comments section below.