Padrão Observer - Javascript

O que é o Padrão Observer
É um padrão de design de software no qual um objeto (chamado de
Subject
), mantém uma lista de seus dependentes (Observers
) e os notifica automaticamente sobre qualquer alteração de estado, geralmente invocando um de seus métodos.
Este padrão define um relacionamento um para muitos; Assim, quando um objeto (subject
) é atualizado, ele notifica todos outros objetos (observers
) de que eles foram atualizados.
Quando começamos a estudar padrões de projeto, é difícil imaginar quando podemos usar ou como podemos identificar se estão sendo usados e aonde estariam aplicados.
Se pararmos pra pensar, ele é utilizado por muitas aplicações e frameworks na web. Alguns exemplos que me vieram à cabeça ao estudar o padrão recentemente foi o "Framework Progressivo" VueJs e a lib React. De fato, é assim que a reatividade funciona em alguns desses framework's.
Imagine que temos vários estados na nossa aplicação e queremos que os estados sejam atualizados quando algo importante acontece.
Analogia
Vamos analisar um exemplo da vida real, imagine como uma newsletter funciona:
- Seu blog preferido começa a publicar vários artigos na semana, logo você não irá querer perder as novidades.
- Você então resolve assinar a newsletter, agora sempre será avisado quando algo novo for publicado, até o momento que você não quiser mais.
- Em um segundo momento você resolve que não é mais interessante receber aquilo, então você cancela a assinatura e o blog pára de enviar as novidades.
- Enquanto você cancela, podem ter várias outras pessoas assinando e cancelando a assinatura.
No padrão observer, o Blog seria o Subject e você seria o Observer.
Prática
Para implementar os padrões de projeto temos que ter em mente que a grande maioria deles tem um contrato a ser seguido. Ele pode ser representado em progração orientada a objetos como uma interface
, como não temos esse recurso, iremos implementar classes que representam nossos contratos, onde outras classes podem extender delas.
Classe Subject
Nós teremos a classe Subject que irá manter uma lista de Observers que precisam ser notificados quando ocorrer uma atualização e também terá outras responsabilidades como adicionar ou remover Observers.
Classe Observer
O objetivo da classe Observer é implementar um método update() que será chamado pelo método Subject notify(). Onde o update será responsável por renderizar o elemento novamente.
Mini biblioteca
Vamos ver como seria esse código na prática implementando uma mini lib de estados e renderização similar ao que o React
faz. Nosso projetinho será o famoso TODO list.
Subject: aqui teremos o contrato/métodos que serão implementados ou herdados, ele é reponsável por notificar todos os observadores.
class Subject {
constructor() {
this.observers = []
}
subscribe(observer) {
this.observers.push(observer);
}
unsubscribe(observer) {
this.observers = this.observers.filter(subscriber => subscriber !== observer);
}
notify(data) {
if (this.observers.length > 0) {
this.observers.forEach(observer => observer.update(data))
}
}
}
export default Subject
Observer: aqui vemos o contrato do obersevador, onde ele tem um método para atualização dos seus objetos.
class Observer {
update() {}
}
export default Observer
Store: responsável por manter o estado da nossa aplicação, ele assina o contrato/herda de Subject, nele temos como recuperar um estado usando método get()
e temos como atualizar usando método update()
onde dentro dele é executado o método notify()
, responsável por atualizar a aplicação passando o estado.
import Subject from './Subject'
class Store extends Subject {
constructor() {
super()
this.store = {}
}
update(data = {}) {
this.store = Object.assign(this.store, data)
this.notify(this.store)
}
get() {
return this.store
}
}
export default Store
O Exemplo completo estará no link.