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.

Categories: Java

Tomas Zezula

Hello! I'm a technology enthusiast with a knack for solving problems and a passion for making complex concepts accessible. My journey spans across software development, project management, and technical writing. I specialise in transforming rough sketches of ideas to fully launched products, all the while breaking down complex processes into understandable language. I believe a well-designed software development process is key to driving business growth. My focus as a leader and technical writer aims to bridge the tech-business divide, ensuring that intricate concepts are available and understandable to all. As a consultant, I'm eager to bring my versatile skills and extensive experience to help businesses navigate their software integration needs. Whether you're seeking bespoke software solutions, well-coordinated product launches, or easily digestible tech content, I'm here to make it happen. Ready to turn your vision into reality? Let's connect and explore the possibilities together.