The observer pattern and nested objects

I'm just struggling a little with the observer pattern and preventing observers from registering multiple times. I've got a model that implements an Observable interface, so registerObserver/removeObserver and updateObserver functions, and a View with a constructor that calls this.model.registerObserver(this). The problem is each view can have nested views, and those views are created with the new keyword. That means (I think) that I'm unable to run a check in the registerObserver function to make sure that the view isn't already registered :/ Am a bit stuck! For example: The Model
export abstract class Model<T> implements Observable {
observers: Observer[] = [];

registerObserver(observer: Observer): void {
this.observers.push(observer);
}
unregisterObserver(observer: Observer): void {
this.observers = this.observers.filter((obs) => obs !== observer);
}
updateObservers(): void {
this.observers.forEach((observer) => observer.update());
}
export abstract class Model<T> implements Observable {
observers: Observer[] = [];

registerObserver(observer: Observer): void {
this.observers.push(observer);
}
unregisterObserver(observer: Observer): void {
this.observers = this.observers.filter((obs) => obs !== observer);
}
updateObservers(): void {
this.observers.forEach((observer) => observer.update());
}
The View
export abstract class View<T extends Model<K>, K> implements Observer {

constructor(public parent: Element, public model: T) {
if (model) this.bindModel();
}
bindModel(): void {
this.model.registerObserver(this);
}

update() {
this.render();
}

{snip - event/region logic}

onRender(): void {}

render(): void {
{snip - templating logic}

this.onRender();
this.parent.append(templateElement.content);
}
}
export abstract class View<T extends Model<K>, K> implements Observer {

constructor(public parent: Element, public model: T) {
if (model) this.bindModel();
}
bindModel(): void {
this.model.registerObserver(this);
}

update() {
this.render();
}

{snip - event/region logic}

onRender(): void {}

render(): void {
{snip - templating logic}

this.onRender();
this.parent.append(templateElement.content);
}
}
Concrete implementation of the View above that involves nested Views (only looking at onRender) FormView (extends View):
onRender(): void {
const userShow = new UserShow(this.regions.userShow, this.model);
userShow.render();
const userForm = new UserForm(this.regions.userForm, this.model);
userForm.render();
}
onRender(): void {
const userShow = new UserShow(this.regions.userShow, this.model);
userShow.render();
const userForm = new UserForm(this.regions.userForm, this.model);
userForm.render();
}
No doubt this is basic, but I'm stuck! 😆 **After many shit ideas, chatGPT has suggested each View is assigned a random id, which I guess would work, but there must be a better solution
0 Replies
No replies yetBe the first to reply to this messageJoin
Want results from more Discord servers?
Add your server