1
Software Architecture and
Design
Design Patterns Part-2
Observer Pattern
Instructor Name: Riaz Ahmad
09.09.2025 Department of Computer Science, COMSATS University Islamabad, Wah Campus, Pakistan
Outline
2
Type of Design Patterns?
Classification of Design Patterns?
Elements of a Design Pattern
Design Patterns Classification
Benefits of Design Patterns
Observer Pattern
Implementation Examples
Summery of the lecture
What next…….. 09.09.2025
Quotation of today…..
3
“A design that doesn’t take change into account risks major
redesign in the future.”
Erich Gamma
Design Patterns: Elements of Reusable Object-Oriented Software
“Humans are pattern-seeking story-telling animals, and we
are quite adept at telling stories about patterns, whether
they exist or not.”
Michael Shermer
09.09.2025
Design Pattern……
4
A pattern is a recurring solution to a standard problem, in a context.
Christopher Alexander, a professor of architecture…
Why would what a prof of architecture says be relevant to software?
“A pattern describes a problem which occurs over and over again in our environment,
and then describes the core of the solution to that problem, in such a way that you can
use this solution a million times over, without ever doing it the same way twice.”
Jim Coplein, a software engineer:
“I like to relate this definition to dress patterns…”
What are dress patterns?
“... I could tell you how to make a dress by specifying the route of
a scissors through a piece of cloth in terms of angles and lengths of cut. Or, I could give
you a pattern. Reading the specification, you would have no idea what was being built or
if you had built the right thing when you were finished. The pattern foreshadows the
product: it is the rule for making the thing, but it is also, in many respects, the thing
itself.”
09.09.2025
Design Pattern are NOT
5
Data structures that can be encoded in classes and reused as is (i.e., linked lists,
hash tables)
Complex domain-specific designs
(for an entire application or subsystem)
If they are not familiar data structures or complex domain-specific subsystems,
what are they?
They are:
“Descriptions of communicating objects and classes
that are customized to solve a general design problem
in a particular context.”
09.09.2025
THREE TYPE OF PATTERNS
6
Creational patterns:
Deal with initializing and configuring classes and objects
Structural patterns:
Deal with decoupling interface and implementation of classes and objects
Composition of classes or objects
Behavioral patterns:
Deal with dynamic interactions among societies of classes and objects
How they distribute responsibility
09.09.2025
Creational Patterns
7
Abstract Factory:
Factory for building related objects
Builder:
Factory for building complex objects incrementally
Factory Method:
Method in a derived class creates associates
Prototype:
Factory for cloning new instances from a prototype
Singleton:
Factory for a singular (sole) instance
09.09.2025
Structural Patterns
8
Adapter:
Translator adapts a server interface for a client
Bridge:
Abstraction for binding one of many implementations
Composite:
Structure for building recursive aggregations
Decorator:
Decorator extends an object transparently
Facade:
Simplifies the interface for a subsystem
Flyweight:
Many fine-grained objects shared efficiently.
Proxy:
One object approximates another
09.09.2025
Behavioral Patterns
9
Chain of Responsibility:
Request delegated to the responsible service provider
Command:
Request or Action is first-class object, hence re-storable
Iterator:
Aggregate and access elements sequentially
Interpreter:
Language interpreter for a small grammar
Mediator:
Coordinates interactions between its associates
Memento:
Snapshot captures and restores object states privately
Which ones do you think you have seen somewhere?
09.09.2025
Behavioral Patterns continued…
10
Observer:
Dependents update automatically when subject changes
State:
Object whose behavior depends on its state
Strategy:
Abstraction for selecting one of many algorithms
Template Method:
Algorithm with some steps supplied by a derived class
Visitor:
Operations applied to elements of a heterogeneous object structure
09.09.2025
Benefits of Design Patterns
11
Design patterns enable large-scale reuse of software
architectures and also help document systems.
Patterns explicitly capture expert knowledge and design
tradeoffs and make it more widely available.
Patterns help improve developer communication
Pattern names form a common vocabulary
09.09.2025
observer design pattern
According to GoF, observer design pattern intent is;
Define a one-to-many dependency between objects so that when one object changes
state, all its dependents are notified and updated automatically.
Subject contains a list of observers to notify of any change in its state, so it should
provide methods using which observers can register and unregister themselves.
Subject also contain a method to notify all the observers of any change and either it
can send the update while notifying the observer or it can provide another method to
get the update.
Observer should have a method to set the object to watch and another method that
will be used by Subject to notify them of any updates.
Java provides inbuilt platform for implementing Observer pattern
through java.util.Observable class and java.util.Observer interface.
observer design pattern
Java Message Service (JMS) uses Observer design pattern along
with Mediator pattern to allow applications to subscribe and publish data to
other applications.
Model-View-Controller (MVC) frameworks also use Observer pattern where
Model is the Subject and Views are observers that can register to get
notified of any change to the model.
Real world example of observer pattern
A real-world example of observer pattern can be any social media platform
such as Facebook or twitter. When a person updates his status – all his
followers gets the notification. A follower can follow or unfollow another
person at any point of time.
UML Diagram of Observer Pattern
Sample Code for Implementation
class Subject:
""" Know its observers.
Any number of Observer objects may observe a subject.
Send a notification to its observers when its state changes. ""“
def __init__(self):
self._observers = set()
self._subject_state = None
def attach(self, observer):
observer._subject = self
self._observers.add(observer)
def detach(self, observer):
observer._subject = None
self._observers.discard(observer)
def _notify(self):
for observer in self._observers:
observer.update(self._subject_state)
def subject_state(self):
return self._subject_state
@subject_state.setter
def subject_state(self, arg):
self._subject_state = arg
self._notify()
Sample Code for Implementation…
class Observer(metaclass=abc.ABCMeta):
"""
Define an updating interface for objects that should be notified of changes in a subject.
""“
def __init__(self):
self._subject = None
self._observer_state = None
@abc.abstractmethod
def update(self, arg):
Pass
class ConcreteObserver(Observer):
""" Implement the Observer updating interface to keep its state consistent with the subject's. Store state that should stay consistent with the subject's. ""“
def update(self, arg):
self._observer_state = arg
# ...
def main():
subject = Subject()
concrete_observer = ConcreteObserver()
subject.attach(concrete_observer)
subject.subject_state = 123
if __name__ == "__main__":
main()
More Example to grasp the concept
Example 1: observer1.py
class Subscriber:
def __init__(self, name):
self.name = name
def update(self, message):
print('{} got message "{}"'.format(self.name, message))
class Publisher:
def __init__(self):
self.subscribers = set()
def register(self, who):
self.subscribers.add(who)
def unregister(self, who):
self.subscribers.discard(who)
def dispatch(self, message):
for subscriber in self.subscribers:
subscriber.update(message)
More Example to grasp the concept
Example 2: driver_observer1.py
from observer1 import Publisher, Subscriber pub = Publisher()
bob = Subscriber('Bob')
alice = Subscriber('Alice')
john = Subscriber('John')
pub.register(bob)
pub.register(alice) pub.register(john) pub.dispatch("It's lunchtime!")
pub.unregister(john)
pub.dispatch("Time for dinner")
More Example to grasp the concept
Example 1: observer2.py
class SubscriberOne:
def __init__(self, name):
self.name = name
def update(self, message):
print('{} got message "{}"'.format(self.name, message))
class SubscriberTwo:
def __init__(self, name):
self.name = name
def receive(self, message):
print('{} got message "{}"'.format(self.name, message))
class Publisher:
def __init__(self):
self.subscribers = dict()
def register(self, who, callback=None):
if callback == None:
callback = getattr(who, 'update')
self.subscribers[who] = callback
def unregister(self, who):
del self.subscribers[who]
def dispatch(self, message):
for subscriber, callback in self.subscribers.items():
callback(message)
More Example to grasp the concept
Example 2: driver_observer2.py
from observer2 import Publisher, SubscriberOne, SubscriberTwo
pub = Publisher()
bob = SubscriberOne('Bob')
alice = SubscriberTwo('Alice')
john = SubscriberOne('John')
pub.register(bob, bob.update)
pub.register(alice, alice.receive)
pub.register(john)
pub.dispatch("It's lunchtime!")
pub.unregister(john)
pub.dispatch("Time for dinner")
More Example to grasp the concept
Example 1: observer3.py
class Subscriber:
def __init__(self, name): self.name = name
def update(self, message): print('{} got message "{}"'.format(self.name, message))
class Publisher:
def __init__(self, events):
# maps event names to subscribers
# str -> dict
self.events = { event : dict() for event in events }
def get_subscribers(self, event):
return self.events[event]
def register(self, event, who, callback=None):
if callback == None:
callback = getattr(who, 'update')
self.get_subscribers(event)[who] = callback
def unregister(self, event, who):
del self.get_subscribers(event)[who]
def dispatch(self, event, message):
for subscriber, callback in self.get_subscribers(event).items():
callback(message)
More Example to grasp the concept
Example 2: driver_observer3.py
from observer3 import Publisher, Subscriber
pub = Publisher(['lunch', 'dinner'])
bob = Subscriber('Bob')
alice = Subscriber('Alice')
john = Subscriber('John')
pub.register("lunch", bob)
pub.register("dinner", alice)
pub.register("lunch", john)
pub.register("dinner", john)
pub.dispatch("lunch", "It's lunchtime!") pub.dispatch("dinner", "Dinner is served")
24 09.09.2025
25 09.09.2025
26
THANK YOU
09.09.2025