VIDEO REFERENCE LECTURE NOTES — LOW LEVEL DESIGN
Observer Design Pattern Architecture
1. Introduction to the Observer Design Pattern [00:00:05]
The Observer Design Pattern is a behavioral design pattern used to establish a state-synchronized linkage across
isolated components. It is primarily applied to solve architectural challenges where one change in an entity requires
an instant update across a set of dependent objects.
Core Theoretical Foundations [00:00:33]
• One-to-Many Relationship: It binds a single provider instance (the Subject/Observable) to a dynamic list of
consumers (the Observers).
• State Dependency: When the central Observable changes its internal state, it cycles through its registered
dependents and alerts them automatically.
• The Fallback (Polling vs. Pushing) [00:02:43]: In a traditional Polling environment, observers repeatedly ping
the subject to verify changes. This introduces high CPU overhead and synchronization latency. The Observer
Pattern shifts this paradigm to a Pushing model, where the Subject owns the responsibility of broadcasting
updates.
2. Architectural Violations: Single Responsibility Principle (SRP) [00:24:21]
A classic implementation of the Observer pattern introduces a subtle trade-off regarding the Single Responsibility
Principle (SRP).
The SRP Paradox [00:24:32]:
In standard design setups, the ConcreteObservable (e.g., our Concrete YouTube Channel) handles two
distinct responsibilities simultaneously:
1. Core Business Logic: Handling video encoding, executing stream titles, tracking description properties,
and core state changes.
2. Subscription Mechanics: Managing observer collection arrays, adding elements via pointers, removing
instances on demand, and looping through lists to push notifications.
Mitigation & Engineering Trade-off [00:25:08]
To avoid over-complicating class architectures, engineers accept this violation as a controlled trade-off. Because
subscription mechanics remain structurally static over time while business logic grows dynamically, bundling them
into a single concrete wrapper is a practical approach supported by standard UML definitions.
Low-Level Design Mastery Series • Coder Army Reference Core Page 1
3. Structural UML Diagrams
A. Standard Formal UML Model
The standard model defines abstract interfaces to decouple concrete subjects from target tracking consumers.
+-----------------------------------+ +-----------------------------------+
| <<Interface>> | | <<Interface>> |
| IObservable | | IObserver |
+-----------------------------------+ +-----------------------------------+
| + add(observer: IObserver) |1 * | + update() |
| + remove(observer: IObserver) |------------->| |
| + notify() | | |
+-----------------------------------+ +-----------------------------------+
^ ^
| Realizes | Realizes
| |
+-----------------------------------+ +-----------------------------------+
| ConcreteObservable | | ConcreteObserver |
+-----------------------------------+ +-----------------------------------+
| - observers: List<IObserver> | | - subject: ConcreteObservable |
| - state |<------------| |
+-----------------------------------+ Associates +-----------------------------------+
| + getState() | | + update() |
| + setState() | | |
+-----------------------------------+ +-----------------------------------+
B. YouTube Practical Domain UML Model [00:19:07]
This customized model maps the interfaces directly to a real-world YouTube subscription and alert infrastructure.
+----------------------------------------+ +-----------------------------------+
| <<Interface>> | | <<Interface>> |
| IChannel | | ISubscriber |
+----------------------------------------+ +-----------------------------------+
| + subscribe(s: ISubscriber) |1 * | + update() |
| + unsubscribe(s: ISubscriber) |------->| |
| + notifySubscribers() | | |
+----------------------------------------+ +-----------------------------------+
^ ^
| Realizes | Realizes
| |
+----------------------------------------+ +-----------------------------------+
| YoutubeChannel | | ConcreteSubscriber |
+----------------------------------------+ +-----------------------------------+
| - subscribers: List<ISubscriber> | | - name: String |
| - latestVideoTitle: String |<-------| - channelRef: YoutubeChannel* |
+----------------------------------------+ Has A +-----------------------------------+
| + uploadVideo(title: String) | | + update() |
| + getVideoData(): String | | |
+----------------------------------------+ +-----------------------------------+
4. Production-Grade C++ Implementation [00:20:44]
Below is the complete, high-fidelity C++ implementation of the YouTube notification subsystem using a clean, VS-
Code styled code representation.
Low-Level Design Mastery Series • Coder Army Reference Core Page 2
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
// Forward declaration to resolve circular dependency bindings
class ISubscriber;
// --- SUBJECT INTERFACE --- [00:08:27]
class IChannel {
public:
virtual void subscribe(ISubscriber* subscriber) = 0;
virtual void unsubscribe(ISubscriber* subscriber) = 0;
virtual void notifySubscribers() = 0;
virtual ~IChannel() {}
};
// --- OBSERVER INTERFACE --- [00:08:46]
class ISubscriber {
public:
virtual void update() = 0;
virtual ~ISubscriber() {}
};
// --- CONCRETE SUBJECT --- [00:20:55]
class YoutubeChannel : public IChannel {
private:
vector<ISubscriber*> subscribers;
string channelName;
string latestVideoTitle;
public:
YoutubeChannel(string name) : channelName(name) {}
void subscribe(ISubscriber* subscriber) override {
// Prevent duplicate registrations inside the tracking engine [00:21:11]
auto it = find([Link](), [Link](), subscriber);
if (it == [Link]()) {
subscribers.push_back(subscriber);
}
}
void unsubscribe(ISubscriber* subscriber) override {
// Erase subscriber reference from structural storage [00:21:19]
auto it = find([Link](), [Link](), subscriber);
if (it != [Link]()) {
[Link](it);
}
}
void notifySubscribers() override {
// Dispatch updates across the subscriber graph [00:21:24]
for (ISubscriber* sub : subscribers) {
sub->update();
}
}
Low-Level Design Mastery Series • Coder Army Reference Core Page 3
void uploadVideo(string title) {
latestVideoTitle = title;
cout << "\n[SYSTEM] Channel '" << channelName << "' uploaded: " << title << endl;
notifySubscribers(); // Cascade update trigger [00:21:48]
}
string getVideoData() {
return "Check out our new video: " + latestVideoTitle;
}
string getChannelName() {
return channelName;
}
};
// --- CONCRETE OBSERVER --- [00:22:04]
class ConcreteSubscriber : public ISubscriber {
private:
string subscriberName;
YoutubeChannel* channelRef; // Reference pointer link [00:14:25]
public:
ConcreteSubscriber(string name, YoutubeChannel* channel)
: subscriberName(name), channelRef(channel) {}
void update() override {
// Fetch new state from the coupled channel reference instance [00:22:34]
string videoData = channelRef->getVideoData();
cout << " Notification to >> [" << subscriberName << "]: Hello! '"
<< channelRef->getChannelName() << "' just pushed an update. -> "
<< videoData << endl;
}
};
// --- MAIN EXECUTION ROUTINE --- [00:22:53]
int main() {
// Instantiate Concrete Youtube Channel Platform
YoutubeChannel* coderArmy = new YoutubeChannel("Coder Army");
// Instantiate Active Subscribing Listeners
ConcreteSubscriber* varun = new ConcreteSubscriber("Varun", coderArmy);
ConcreteSubscriber* tarun = new ConcreteSubscriber("Tarun", coderArmy);
// Attach subscriptions inside Subject Engine [00:23:13]
coderArmy->subscribe(varun);
coderArmy->subscribe(tarun);
// Event Trigger 1: Uploading Video [00:23:34]
coderArmy->uploadVideo("Observer Pattern Tutorial");
// Unsubscribe Operation execution [00:23:49]
coderArmy->unsubscribe(varun);
// Event Trigger 2: Post Unsubscribe Broadcast Sequence
coderArmy->uploadVideo("Decorator Pattern Tutorial");
// Structural Memory Deallocations
delete varun;
Low-Level Design Mastery Series • Coder Army Reference Core Page 4
delete tarun;
delete coderArmy;
return 0;
}
Low-Level Design Mastery Series • Coder Army Reference Core Page 5