Skip to content
BBaskaran

Observer

Notify many dependent objects automatically when one object changes.

Use it when

Changes to one object must be reflected in others without tight coupling.

// Observer
interface IDataViewObserver {
	notify(data: number[]): void;
	render(data: number[]): void;
	delete(): void;
}

class ChartView implements IDataViewObserver {

	private _observable: IDataModelObservable;
	private _id: number;

	constructor(observable: IDataModelObservable) {
		this._observable = observable;
		this._id = this._observable.subscribe(this);
	}

	notify(data: number[]): void {
		console.log("ChartView notify...")
		this.render(data);
	}
	render(data: number[]): void {
		console.log("ChartView rendering..." + JSON.stringify(data));
	}
	delete(): void {
		this._observable.unsubscribe(this._id);
	}
}

class TableView implements IDataViewObserver {
	private _observable: IDataModelObservable;
	private _id: number;

	constructor(observable: IDataModelObservable) {
		this._observable = observable;
		this._id = this._observable.subscribe(this);
	}

	notify(data: number[]): void {
		console.log("TableView notify...")
		this.render(data);
	}
	render(data: number[]): void {
		console.log("TableView rendering..." + JSON.stringify(data));
	}
	delete(): void {
		this._observable.unsubscribe(this._id);
	}
}

interface IDataModelObservable {
	subscribe(observer: IDataViewObserver): number;
	unsubscribe(observerID: number): void;
	notify(data: number[]): void;
}

class DataModel implements IDataModelObservable {

	private _observers: { [id: number]: IDataViewObserver } = {};
	private _counter: number;

	constructor() {
		this._counter = 0;
	}

	subscribe(observer: IDataViewObserver): number {
		this._counter++;
		this._observers[this._counter] = observer;
		return this._counter;
	}
	unsubscribe(observerID: number): void {
		delete this._observers[observerID];
	}
	notify(data: number[]): void {
		Object.keys(this._observers).forEach((obr) => {
			this._observers[parseInt(obr)].notify(data);
		});
	}
}

const clientCode = () => {
	const dataModel = new DataModel();
	const chartView = new ChartView(dataModel);
	const tableView = new TableView(dataModel);

	dataModel.notify([1, 2, 3]);
	tableView.delete();
	dataModel.notify([5, 6, 7, 8, 9, 10]);
}