Photo by Victor Xok on Unsplash.
There are 23 classic design patterns described in the original book Design Patterns: Elements of Reusable Object-Oriented Software. These patterns provide solutions to particular problems often repeated in software development.
In this article, I am going to describe how the Observer pattern works and when it should be applied.
Observer: Basic Idea
Wikipedia provides us with the following definition:
“The observer pattern is a software design pattern in which an object, named the subject, maintains a list of its dependents, called observers, and notifies them automatically of any state changes, usually by calling one of their methods.” — Wikipedia
On the other hand, the definition provided by the original book goes as follows:
“Define a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.”
On many occasions, we need to communicate with system objects without coupling them either at the code or communication mechanism level. Should we have a group of objects (observers) that are required to be aware of the state of another object (observable), there are different techniques for carrying out the communication between them. The most popular techniques are:
- Busy waiting — A process repeatedly verifies a condition. In our case, it would be an observer constantly checking whether or not the observable’s condition has changed. This strategy could be a valid solution in certain cases, but it isn’t an adequate solution for our scenario since it would imply having several processes (observers) consuming resources without performing any operations, causing an exponential performance decrease in the number of existing observers.
- Polling — In this case, the query operation is performed with a small window of time between operations. This is an attempt to implement synchronism between processes. However, we can once again appreciate degradation in the system’s performance. Furthermore, depending on the time set between each query, the information can be so delayed that it might be invalid, causing a waste of resources.
The following codes show implementations of these techniques.
- Busy waiting:
while(!condition){
// Query
if(isQueryValid) condition = true;
}
- Polling:
Although it isn’t the goal of this post, it’s a good idea to understand the two alternative techniques to this design pattern. Therefore, in a nutshell, the difference between the active wait and polling techniques is that the query operation is performed all the time in the former, while there are intervals of time where the operation isn’t executed in the latter.
- Busy waiting:
while(resourceIsNotReady()){
//Do nothing
}
- Polling:
while(resourceIsNotReady()){
Sleep(1000); // 1000 or anytime
}
The Observer pattern allows us to achieve a more efficient and less coupled code since it avoids the previously mentioned issue. It also has other advantages regarding code maintainability. Here is the UML pattern of this pattern:
UML diagram from the book Design Patterns: Elements of Reusable Object-Oriented Software.
These are the classes that comprise this pattern:
Subject
is the interface that every observed class implements. This interface contains theattach
anddetach
methods that allow us to add and remove observers from the class. It also contains anotify
method that is responsible for notifying all of the observers that a change has occurred in the observed. Also, all of thesubjects
store references of the objects that observe them (observers
).Observer
is the interface that all of theConcreteObservers
implement. In this interface, theupdate
method is defined and contains the business logic to be executed by each observer upon receiving the change notification from theSubject
.ConcreteSubject
is the concrete implementation of theSubject
class.
This class defines the state of theSubjectState
application that must be notified when a change occurs. For this reason, the accessor methods (getState
andsetState
) are usually implemented since they manipulate the state. This class is also responsible for sending the notification to all of its observers when the state changes.ConcreteObserver
is the class that models each of the concrete observers. In this class, theupdate
method belonging to theObserver
interface is implemented. It is responsible for consistently maintaining its state, which is responsible for keeping its state consistent with thesubject
objects it is observing.
Nowadays, there’s a family of libraries known as Reactive Extensions or ReactiveX that have made this design pattern popular. The Reactive extensions make use of two design patterns:
- Observer
- Iterator.
They also have a group of operators that use functional programming. These are some of the most popular Reactive extensions:
In these implementations, there are differences in the naming of classes and methods. The following names are the most extended:
Subscriber
corresponds with the classObserver
.
2. ConcreteSubscribers
correspond with the classes ConcreteObservers
.
3. The Subject
class is maintained. The attach
and detach
methods are renamed to subscribe
and unsubscribe
.
4. The ConcreteSubjects
classes are concrete implementations, like BehaviorSubject
, ReplaySubject
, or AsyncSubject
.
Observer Pattern: Communication Strategies
There are two communication strategies between Subjects
(observables) and Observers
(observers) in the Observer pattern:
- Pull — In this model, the
subject
sends the minimum information to theobserver
and they are responsible for making inquiries to obtain more details. This model focuses on the fact that theSubject
ignores theobserver
. - Push — In this model, the
subject
sends the greatest amount of information to theobserver
that the change produced, regardless of whether they wanted it or not. In this model, theSubject
knows the needs of each of itsobservers
in-depth.
Although it may seem a priori that the push
communication technique is less reusable due to the fact that the Subject
must have knowledge about the observer
, this is not always the case. On the other hand, the pull
-based communication technique can be inefficient because the observer
has to figure out what changed without help from the Subject
.
Observer Pattern: When To Use It
- When there is a one-to-many dependency between system objects so that when the object changes state, all dependent objects need to be notified automatically.
- You do not want to use busy waiting and polling to update observers.
- Decouple the dependencies between the
Subject
objects (observables) and theObservers
(observers), allowing you to respect the Open-Closed Principle.
Observer Pattern: Advantages and Disadvantages
The Observer pattern has a number of advantages that can be summarized in the following points:
- The code is more maintainable because it is less coupled between the observable classes and their dependencies (the observers).
- Clean code. The Open-Closed Principle is guaranteed since the new observers (subscribers) can be introduced without breaking the existing code in the observable (and vice versa).
- Cleaner code. The Single Responsibility Principle (SRP) is respected since the responsibility of each observer is transferred to its
update
method instead of having that business logic in theObservable
object.
Note: Relationships between objects can be established at runtime rather than at compile time.
However, the main drawback of the Observer pattern — like most design patterns — is that there is an increase in code complexity and the number of classes required for the code. With that said, this disadvantage is well known when applying design patterns since it’s the price to pay for gaining abstraction in the code.
Observer Pattern Examples
Next, we are going to illustrate two examples of the Observer pattern:
- The basic structure of the Observer pattern. In this example, we are going to translate the theoretical UML diagram into TypeScript code to identify each of the classes involved in the pattern.
- An auction system in which there is an object (
subject
) that emits the change produced (push
technique) in theprice
of aproduct
that is being auctioned to all observers (observer
) interested in acquiring thatproduct
. Every time theprice
of theproduct
auction increases because someobservador
has increased the bid, it is notified to all observers.
The following examples will show the implementation of this pattern using TypeScript. We have chosen TypeScript to carry out this implementation rather than JavaScript. The latter lacks interfaces or abstract classes, so the responsibility of implementing both the interface and the abstract class would fall on the developer.
Example 1: Basic Structure of the Observer Pattern
In this first example, we’re going to translate the theoretical UML diagram into TypeScript to test the potential of this pattern. This is the diagram to be implemented:
UML diagram from the book Design Patterns: Elements of Reusable Object-Oriented Software.
First, we are going to define the interface (Subject
) of our problem. Being an interface, all the methods that must be implemented in all the specific Subject
are defined. In our case, there is only one: ConcreteSubject
. The Subject
interface defines the three methods necessary to comply with this pattern: attach
, detach
, and notify
. The attach
and detach
methods receive the observer
as a parameter that will be added or removed in the Subject
data structure.
Subject
There can be as many ConcreteSubjects
as we need in our problem. As this problem is the basic scheme of the Observer pattern, we only need a single ConcreteSubject
. In this first problem, the state that is observed is the state
attribute, which is of type number
. On the other hand, all observers
are stored in an array called observer
. The attach
and detach
methods check whether or not the observer
is previously in the data structure to add or remove it from it. Finally, the notify
method is in charge of invoking the update
method of all the observers
that are observing the Subject
.
Objects of the ConcreteSubject
class perform some task related to the specific business logic of each problem. In this example, there is a method called operation
that is in charge of modifying the state
and invoking the notify
method.
ConcreteSubject
The other piece of this design pattern is the observer
. Therefore, let’s start by defining the Observer
interface, which only needs to define the update
method that is in charge of executing every time an observer
is notified that a change has occurred.
Observer
Each class that implements this interface must include its business logic in the update
method. In this example, two ConcreteObservers
have been defined. They will perform actions according to the Subject
’s state
. The following code shows two concrete implementations for two different types of observers: ConcreteObserverA
and ConcreteObserverB
.
ConcreteObserverA
ConcreteObserverB
Finally, we define our Client
or Context
class that makes use of this pattern. In the following code, the necessary classes to simulate the use of Subject
and Observer
are implemented:
Example 2: Auctions Using Observer
In this example, we’re going to use the Observer pattern to simulate an auction house in which a group of auctioneers (Auctioneer
) bid for different products (product
). The auction is directed by an agent (Agent
). All of our auctioneers need to be notified each time one of them increases their bid so that they can decide whether to continue bidding or to retire.
Like we did in the previous example, let’s begin by taking a look at the UML diagram that is going to help us identify each of the parts that this pattern is composed of.
Observer pattern
The product
that is being auctioned is the Subject
’s state, and all of the observers
await notifications whenever it changes. Therefore, the product
class is comprised of three attributes: price
, name
, and auctionner
(the auctioneer that is assigned the product).
Product
The Agent
is the interface that defines the methods for managing the group of Auctioneers
and notifying them that the bid on the auctioned product has changed. In this case, the attach
and detach
methods have been renamed to subscribe
and unsubscribe
.
Agent
The concrete implementation of the Agent
interface is performed by the ConcreteAgent
class. As well as the three methods previously described that have a very similar behavior to the one presented in the previous example, the bidUp
method has been implemented. After making some checks on the auctioneer’s bid, it assigns it as valid and notifies all of the auctioneers of the change.
In this problem, there are four different types of Auctioneer
defined in the AuctioneerA
, AuctioneerB
, AuctioneerC
, and AuctioneerD
classes. All of these auctioneers implement the Auctioneer
interface, which defines the name
, MAX_LIMIT
, and the update
method. The MAX_LIMIT
attribute defines the maximum amount that can be bid by each type of Auctioneer
.
https://lachartreusedeneuville.org/forums/topic/free-watch-octonauts-the-ring-of-fire-2021-hd-full-movie-online/
https://lachartreusedeneuville.org/forums/topic/free-watch-the-dry-2021-hd-full-movie-online/
https://lachartreusedeneuville.org/forums/topic/free-watch-wish-dragon-2021-hd-full-movie-online/
https://lachartreusedeneuville.org/forums/topic/free-watch-peter-rabbit-2-the-runaway-2021-hd-full-movie-online/
https://lachartreusedeneuville.org/forums/topic/free-watch-the-little-things-2021-hd-full-movie-online/
https://lachartreusedeneuville.org/forums/topic/free-watch-cinderella-2021-hd-full-movie-online/
https://lachartreusedeneuville.org/forums/topic/free-watch-finding-ohana-2021-hd-full-movie-online/
https://lachartreusedeneuville.org/forums/topic/free-watch-the-little-things-2021-hd-full-movie-online/
https://lachartreusedeneuville.org/forums/topic/free-watch-penguin-bloom-2021-hd-full-movie-online/
https://lachartreusedeneuville.org/forums/topic/free-watch-wrong-turn-2021-hd-full-movie-online/
https://lachartreusedeneuville.org/forums/topic/free-watch-born-a-champion-2021-hd-full-movie-online/
https://lachartreusedeneuville.org/forums/topic/free-watch-no-mans-land-2021-hd-full-movie-online/
https://lachartreusedeneuville.org/forums/topic/free-watch-our-friend-2021-hd-full-movie-online/
https://lachartreusedeneuville.org/forums/topic/free-watch-gintama-the-final-2021-hd-full-movie-online/
https://lachartreusedeneuville.org/forums/topic/free-watch-pretty-guardians-sailor-moon-eternal-part-1-2021-hd-full-movie-onli/
https://lachartreusedeneuville.org/forums/topic/free-watch-the-marksman-2021-hd-full-movie-online/
https://lachartreusedeneuville.org/forums/topic/free-watch-outside-the-wire-2021-hd-full-movie-online/
https://lachartreusedeneuville.org/forums/topic/free-watch-the-dig-2021-hd-full-movie-online/
https://lachartreusedeneuville.org/forums/topic/free-watch-locked-down-2021-hd-full-movie-online/
https://lachartreusedeneuville.org/forums/topic/free-watch-shadow-in-the-cloud-2021-hd-full-movie-online/
https://lachartreusedeneuville.org/forums/topic/free-watch-the-white-tiger-2021-hd-full-movie-online/
https://lachartreusedeneuville.org/forums/topic/free-watch-pvt-chat-2020-hd-full-movie-online/
https://lachartreusedeneuville.org/forums/topic/free-watch-my-salinger-year-2020-hd-full-movie-online/
https://lachartreusedeneuville.org/forums/topic/free-watch-minamata-2020-hd-full-movie-online/
https://lachartreusedeneuville.org/forums/topic/free-watch-the-last-shift-2020-hd-full-movie-online/
https://lachartreusedeneuville.org/forums/topic/free-watch-the-nest-2020-hd-full-movie-online/
https://lachartreusedeneuville.org/forums/topic/free-watch-cosmoball-2020-hd-full-movie-online/
https://lachartreusedeneuville.org/forums/topic/free-watch-jumanji-level-one-2021-hd-full-movie-online/
https://lachartreusedeneuville.org/forums/topic/free-watch-shock-wave-2-2020-hd-full-movie-online/
https://lachartreusedeneuville.org/forums/topic/watch-ufc-257-live-stream-online/
https://lachartreusedeneuville.org/forums/topic/watch-ufc-257-poirier-vs-mcgregor-2-live-stream-online/
https://digg.com/@haris-jamal
https://digg.com/@biby-boll
https://digg.com/@manik-bhai
https://digg.com/@shimuls-denny
https://www.uplabs.com/nivemax633
https://www.uplabs.com/tayih36112
https://www.uplabs.com/tokyo2021
https://www.uplabs.com/kmoviesxyz
https://patch.com/washington/bellevue/ep/1656025
https://cdn.hackaday.io/files/1770247573794816/ufc-257-live-stream.pdf
https://cdn.hackaday.io/files/1770247573794816/ufc-257-live-stream-free.pdf
https://cdn.hackaday.io/files/1770247573794816/ufc-257-live-stream-reddit.pdf
https://cdn.hackaday.io/files/1770247573794816/ufc-257-live-stream-tv.pdf
https://vocus.cc/article/600c0430fd89780001be32e0
https://vocus.cc/article/600c045efd89780001be333e
https://summerolympics2020s.com/doubts-over-virus-tests-but-how-is-still-hazy-attorneys-from-the-alaska-department/
https://xn--z6ut02b7b412h.xyz/acceptance-of-the-governments-arguments-would-effectively-stand/
The different types of Auctioneer
have been defined to illustrate that each one will have a different behavior upon receiving the Agent
’s notification in the update
method. Nevertheless, all that has been modified in this example is the probability of continuing to bid and the amount they increase their bids by.