Differentiating Observer and Publish-Subscribe Patterns

People regularly argue about whether or not the Observer and Publish-Subscribe patterns are equivalent. Many sources list them as equivalent patterns, including the canonical Design Patterns: Elements of Reusable Object-Oriented Software by Gamma et al., the C2 Wiki, and Making Embedded Systems: Design Patterns for Great Software by Elecia White. However, articles and comments on the internet seem insistent that these two patterns are not the same, including the Wikipedia Talk pages for the Observer and Publish-Subscribe pages.

The Claimed Differences

Those who push back against the two patterns being grouped together usually focus on a few points:

  1. In the Observer pattern, Observers are aware of the Subject, but Publish-Subscribe does not require Subjects and Observers to know about each other because they communicate through a central broker. In other words, Observer involves tight coupling to Subjects, but Publish-Subscribe involves loose coupling.
  2. The use of message queues/passing as the primary implementation mechanism for Publish-Subscribe vs. a direct call with the Observer pattern. In other words, Publish-Subscribe is asynchronous, while Observer is synchronous.
  3. Publish-subscribe is a pattern primarily used for communications in distributed systems, but not necessarily internally within systems.

These points do not feel so significant to us that it is worth splitting up the two patterns into different entries. These also seem to make strong assumptions about the patterns that are not backed up in the canonical writings or our experience.

The Use of a Broker

It is strange to say that Observer precludes the use of a broker, since this variant is already described with the pattern in Design Patterns: Elements of Reusable Object-Oriented Software in the Implementation Notes for the Observer Pattern. Here is our rendering of the diagram supplied in the book:


Adjusting the Observer pattern for use with a centralized notification system (Publish-Subscribe style),

How different is that particular design from this publish-subscribe diagram in an article that clearly mentions the use of a message broker?



Or this example from a Hackernoon article saying the patterns are different?



With this point made, some also comment that Publish-Subscribe provides mechanisms for removing interest in a topic through the central broker, while Observer does not. Again, this goes against pretty much every documented discussion of the pattern that we have come across, and the example code provided in the Design Patterns book includes a Detach operation, even without the use of a central broker.

Synchronous vs Asynchronous

The core pattern itself describes the relationship between modules and the behavior of that relationship – particularly subscriptions and notifications when something happens with a subscribed topic. Fundamentally, it does not seem to be an important point to specify how the notifications are delivered or what exact form they take. That is an implementation detail of the broader design pattern. I don’t see why the delivery could not be handed in any number of ways, whether via direct synchronous function call, posting an event to a central broker, adding a function to a dedicated dispatch queue, sending a message to an internal message queue, or sending a message over a network. Given that my preference for event-driven asynchronous programming, almost all callbacks and observer/publish-subscribe systems I’ve designed or used have worked asynchronously, usually dispatching the operations to a dispatch queue or event processing queue. Even if a publish-subscribe pattern is conceived as having a complex message passing broker, that is still an implementation detail of ChangeManager in the diagrams shown above rather than a distinct evolution on the pattern.

Coupling

Fundamentally, subscribing to a “topic” seems no different than subscribing to notifications with an object or module – at some level, you always have to know that a given subscribable item exists as well as the format of the given message or function prototype. You cannot avoid that degree of coupling.

Even if one were to accept that the use of a central broker distinguished the two patterns, it is specious to argue that the Observer pattern involves tighter coupling than a Publish-Subscribe model with a central broker simply because an Observer-style module without a central broker maintains a list of subscribers. Whether or not a broker it is the broker or a subject that maintains the list of subscribers, something is still maintaining a list of subscribers. But the subscription list does not reveal what specific modules are subscribing!

Any tight coupling exists at the call site where one module actually registers itself with a subject module or a central broker. The modules can be structured so that the coupling code is not contained within either module itself, but rather in a region of code designed to contain such tight coupling. Simply maintaining an abstracted list of pointers does not mean that there is tight coupling inside of a module. With a proper design, subjects and observers still will not directly know about each other regardless of whether or not there is a central broker placed in between. This design point cannot be ignored if one is concerned about coupling, since tightly coupling a module to a central broker is still tight coupling.

Closing Thoughts

If you disagree with this assessment, please feel free to comment below. However, our goal is not to change hearts and minds if you are of the opinion that they are two patterns. Rather, we are explaining why we have grouped the two patterns together on the website. Fundamentally, we do not view these two patterns as distinct enough to warrant separate entries. Most of the information would be duplicated, with only minor variations to account for the supposed focus on messages and a central broker with publish-subscribe.

References

Share Your Thoughts

This site uses Akismet to reduce spam. Learn how your comment data is processed.