Reputation: 1349
I have browsed through many articles online trying to grok the essence of the Publisher-Subscriber pattern, but they often:
I'm looking for the most basic, abstract explication of this pattern, not industry story problems or real world analogies. I simply want to know, in the abstract:
What are the bare minimum classes that must exist and what must their interfaces include, to embody the Publisher-Subscriber design pattern in OOP?
Presented with clear, minimal markdown code demonstrations. (Preferably in TypeScript or strictly-annotated Python)
From what I've gathered, it seems that the three main classes are
class Publisher {}
class Subscriber {}
class Broker {}
with potentially other OOP constructs such as Topic
or Event
etc. But I am not sure what methods/attributes each should have.
Upvotes: 1
Views: 734
Reputation: 38094
Publisher-subscriber is a network oriented architectural pattern and Observer is an object-event oriented pattern. They both are used at different Software levels.
In other words, observer is implemented within the boundaries of an application or within a single process. Publish-Subscribe is a cross application communication pattern with messages being exchanged between different processes.
Generally, if we talk about Observer pattern, what we need is just two classes:
So let me show an example. These are abstractions of Observer and Publisher(Subject)
interface IMyObserver
{
update: (myMessage: string) => void;
}
interface IMySubject
{
registerObserver: (o: IMyObserver) => void;
removeObserver: (o: IMyObserver) => void;
notifyObservers: () => void;
}
And this is a concrete implementation of IMyObserver
:
class MyObserver implements IMyObserver
{
_mySubject: MySubject
_myMessage: string | undefined
constructor(mySubject: MySubject)
{
this._mySubject = mySubject;
this._mySubject.registerObserver(this);
}
update(myMessage: string) : void {
this._myMessage = myMessage;
console.log(`Observer have seen this message: ${this._myMessage}`);
}
}
This is a concrete implementation of IMySubject
:
class MySubject implements IMySubject
{
_observers: IMyObserver[] = []
_myMessage?: string
_messageFromObserver?: string
notifyObservers()
{
this._observers.forEach(obs => obs.update(this._myMessage ?? ''))
}
registerObserver(o: IMyObserver):void {
this._observers.push(o)
}
removeObserver(o: IMyObserver) {
const index = this._observers.indexOf(o);
if(index !== -1) {
this._observers.splice(index, 1);
}
}
myMessageChanged() {
this.notifyObservers()
};
setMessage(message: string)
{
this._myMessage = message;
this.myMessageChanged();
}
}
And then you can run the above code like this:
const mySubject = new MySubject();
const myObserver = new MyObserver(mySubject);
// message from subject
mySubject.setMessage("Hello World!");
Upvotes: 1