Software Design Patterns and Principles - Part 12 (Observer Design Pattern)
Source: Webmobtuts

Software Design Patterns and Principles - Part 12 (Observer Design Pattern)

**** Previous Parts ****

Part 1: Introduction

Part 2: List of Most Used Patterns and Singleton Design Pattern

Part 3: Software Design Patterns and Principles - Part 3 (Factory Method and Abstract Factory Method Design Pattern)

Part 4: Software Design Patterns and Principles - Part 4 (Builder Design Pattern)

Part 5: Software Design Patterns and Principles - Part 5 (Adapter Design Pattern)

Part 6: Software Design Patterns and Principles - Part 6 (Decorator Design Pattern)

Part 7: Software Design Patterns and Principles - Part 7 (Composite Design Pattern)

Part 8: Software Design Patterns and Principles - Part 8 (Fa?ade Design Pattern)

Part 9: Software Design Patterns and Principles - Part 9 (Proxy Design Pattern)

Part 10: Software Design Patterns and Principles - Part 10 (Command Design Pattern)

Part 11: Software Design Patterns and Principles - Part 11 (Mediator Design Pattern)


Story:

Roni is owner of a confectionery shop near a girls school. There he sells chocolate, sweet, ice-cream and other thing. Rina is a student of class 10 of this girls school who often visits Roni's shop for buying ice-cream and chocolate. Anik is a neighbor of Roni who likes Rina a lot. As a result, Anik frequently visit Roni's shop and continuously asks about Rina, is he come, when come etc. Here not only Anik, some other little brothers often disturb Roni. So after some days situation got very serious and Roni tells, Anik and others to give him theirs phone number so that he can inform them when Rina and others visits his shop.

Observer Design Pattern:

Definition:

Observer is a behavioral design pattern that lets you define a subscription mechanism to notify multiple objects about any events that happen to the object they’re?observing.

As the definition stat, Observer design pattern gives a subscription mechanism where one or more objects can subscribe to a publisher object and when any change happens then publisher can notify the subscriber object about the changes. Also subscriber can unsubscribe any time if it wanted. So subscriber objects observe the publisher object and react based on it.

Problem:

In the above story, Roni got disturb and situation is not so nice for Anik and others continuous knocking. So he need a solution by which anyone not knocking him, rather he will inform others. How this can be achieved?

The observer design pattern is a widely used pattern in software engineering for implementing distributed event handling systems, in which an object, called the subject, maintains a list of its dependents, called observers, and notifies them of any state changes, usually by calling one of their methods. Here are some scenarios where the observer design pattern can be applied:

  1. User Interface Components: In graphical user interfaces (GUIs), various UI components such as buttons, checkboxes, and sliders often need to react to changes in other components or underlying data. Observers can be used to notify these components of changes, ensuring synchronization and consistency in the UI.
  2. Event Handling Systems: In event-driven systems, such as web applications or games, there are often multiple events occurring simultaneously that need to be handled by different parts of the system. Observers can be employed to listen for specific events and trigger appropriate actions or responses.
  3. Publish-Subscribe Systems: In systems where publishers produce data or events and subscribers consume them, the observer pattern can be used to implement the pub-sub mechanism. Publishers notify subscribers about new data or events, allowing for loose coupling between components.
  4. Model-View-Controller (MVC) Architecture: The observer pattern is a fundamental part of the MVC architecture, where the model represents the data, the view represents the presentation, and the controller acts as an intermediary between them. Views observe changes in the model and update their presentation accordingly.
  5. Databases and Cache Invalidation: In distributed systems with caching mechanisms, changes to data stored in databases need to be reflected in cached copies. Observers can be employed to notify cache instances of data changes, ensuring that cached data remains consistent with the database.
  6. Sensor Networks and IoT: In sensor networks and Internet of Things (IoT) applications, sensors often produce data that needs to be monitored and acted upon in real-time. Observers can be used to track sensor readings and trigger alerts or actions based on predefined thresholds.
  7. Stock Market or Financial Systems: In systems that deal with real-time financial data, such as stock market applications, observers can be used to monitor changes in stock prices, currency exchange rates, or other financial metrics and notify interested parties, such as traders or investors.

Overall, the observer pattern provides a flexible and efficient way to handle communication and coordination between different components of a system, making it a valuable tool in various software development scenarios.

Solution:

In the above story, Roni asked for the phone numbers of Anik and others. So Anik and other give him their phone numbers and tell him to call when their likes person visit his shop. So Roni here is subject/publisher who will inform about the event (here event is Rina and other girls). And Anik and others boy are subscriber whom subscribe Roni by giving their phone number. So as a result, observer pattern solves their problem.

We can also use or implement observer pattern as a solution of the problems stated earlier sections as well.

UML Diagram:

Source: Wikipedia

Here in UML diagram we can see that, There can be multiple ConcreteObserver who is implementing the common Observer interface. Then a Subject class which is mainly the publisher holds the observer list and give a attach and detach mechanism for observer in the subscription list. So when any event happens on Subject it immediately publish or notify the Observer objects.

When to use:

  1. Use the Observer pattern when changes to the state of one object may require changing other objects, and the actual set of objects is unknown beforehand or changes dynamically.
  2. Use the pattern when some objects in your app must observe others, but only for a limited time or in specific cases.

Implementation:

import java.util.ArrayList;
import java.util.List;

// Subject interface
interface Subject {
    void registerObserver(Observer observer);
    void removeObserver(Observer observer);
    void notifyObservers();
}

// Concrete Subject class
class WeatherStation implements Subject {
    private int temperature;
    private List<Observer> observers;

    public WeatherStation() {
        observers = new ArrayList<>();
    }

    public void setTemperature(int temperature) {
        this.temperature = temperature;
        notifyObservers();
    }

    @Override
    public void registerObserver(Observer observer) {
        observers.add(observer);
    }

    @Override
    public void removeObserver(Observer observer) {
        observers.remove(observer);
    }

    @Override
    public void notifyObservers() {
        for (Observer observer : observers) {
            observer.update(temperature);
        }
    }
}

// Observer interface
interface Observer {
    void update(int temperature);
}

// Concrete Observer classes
class PhoneDisplay implements Observer {
    @Override
    public void update(int temperature) {
        System.out.println("Phone Display: Current temperature is " + temperature + " degrees Celsius.");
    }
}

class LaptopDisplay implements Observer {
    @Override
    public void update(int temperature) {
        System.out.println("Laptop Display: Current temperature is " + temperature + " degrees Celsius.");
    }
}

public class ObserverPatternExample {
    public static void main(String[] args) {
        WeatherStation weatherStation = new WeatherStation();

        PhoneDisplay phoneDisplay = new PhoneDisplay();
        LaptopDisplay laptopDisplay = new LaptopDisplay();

        weatherStation.registerObserver(phoneDisplay);
        weatherStation.registerObserver(laptopDisplay);

        // Simulate temperature change
        weatherStation.setTemperature(25);

        // Unregister laptop display
        weatherStation.removeObserver(laptopDisplay);

        // Simulate temperature change again
        weatherStation.setTemperature(30);
    }
}        

Another C# implementation of Observer design pattern.


Achieved Design Principles:

The Observer design pattern helps achieve several Object-Oriented Programming (OOP) and software design principles, including:

  1. Single Responsibility Principle (SRP): The Subject class is responsible for maintaining a list of observers and notifying them of changes. The Observer interface or base class defines the contract for observers without dictating their implementation details. This separation of concerns ensures that each class has a single responsibility, enhancing maintainability and flexibility.
  2. Open/Closed Principle (OCP): The Observer pattern allows for the addition of new observers without modifying the subject class. Subjects can notify any number of observers without needing to know their specific implementations. This promotes code extensibility and reduces the risk of introducing bugs when extending the system.
  3. Liskov Substitution Principle (LSP): Observers can be substituted with different concrete observer implementations without affecting the behavior of the subject. New types of observers can be introduced as long as they adhere to the contract defined by the Observer interface or base class. This principle ensures that derived classes (observers) can be used interchangeably with their base class (Observer), preserving program correctness.
  4. Dependency Inversion Principle (DIP): Subjects depend on abstractions (Observer interface or base class) rather than concrete observer implementations. Observers depend on the subject interface rather than the specific implementation of the subject. This promotes loose coupling between subject and observer classes, making the system more flexible and easier to maintain.
  5. Encapsulation: The Observer pattern encapsulates the communication logic between subjects and observers within the subject class. Observers are isolated from each other and interact with the subject through a well-defined interface. This encapsulation enhances modularity and reduces the risk of unintended interactions between components.
  6. Separation of Concerns: The Observer pattern separates the concerns of data management (subject) from behavior (observers). Subjects focus on managing state and notifying observers, while observers focus on responding to state changes. This separation facilitates code organization, readability, and maintenance.

By adhering to these principles, the Observer pattern promotes good software design practices such as modularity, extensibility, and maintainability, making it a valuable tool for building robust and flexible software systems.


Happy Learning !!!

Happy Coding !!!

Happy Programming !!!

回复

要查看或添加评论,请登录

社区洞察

其他会员也浏览了