Design Pattern – Observer (Parte 02)

Pessoal, bom dia.

Hoje vamos continuar falando sobre o padrão Observer. Seria muito bom que você lesse a primeira parte, caso não o tenha feito Design Pattern – Observer (Parte 01).

Continuando o último post (Design Pattern – Observer (Parte 01)), como poderíamos desacoplar nossas classes?

Um bom modo para criar esse desacoplamento de métodos, seria: a classe Listener passe a ter uma referência da classe Notifier. Bem simples “né”?

Desse modo, a nossa classe Notifier, ela irá apenas dizer ao seu Listener que houve alteração em seu status e o Listener irá buscar todos os parâmetros que necessita.

Continuando no exemplo, que a classe YahooPattern a partir de agora necessitará de uma senha para enviar o email, nossa classe consultaria na classe Notifier os dados que necessitasse. Vamos começar as alterações?

Primeiramente precisamos alterar o método “update”. Para isso, que tal aplicarmos outro modo de “programar para interface”? Vamos atualizar nosso modelo e utilizar uma superclasse abstrata.

Design Pattern - Observer (Parte 02)Design Pattern - Observer (Parte 02)

Alteramos nossa interface Notifier, ela contém agora métodos que serão visíveis aos nossos listeners, para que os listeners possam buscar as informações que necessitarem. As classes que representam o envio de email (EmailPattern) apresentam uma referência do tipo Notifier.

Essa referência foi criada para que o Listener possa buscar os dados que ele quiser e não a Notifier seja o responsável por conhecer a necessidade de cada Listener. Sendo assim, cada Listener pode alterar os parâmetros necessários que nosso método update continuará o mesmo, a alteração seria no método “collectData” que toda classe do tipo EmailPattern é obrigada a construir. Com isso, caso a classe GmailPattern precisasse de senha, apenas ela sofreria alteração e mais ninguém.

Se fosse um novo requisito que a classe HotmailPattern utilizasse certa imagem, bastaria adicionar em nossa classe Notifier um método “get” (como forma acesso), para que a classe HotmailPattern utilizar esse valor. Note que a classe Notifier está sofrendo uma alteração apenas para fornecer uma informação, ela não estará interessada em quem/como estará utilizando essa informação.

Vamos ver nosso código final:

public class EmailSender implements Notifier {

    private List listeners;
    private String emailText;
    private String emailSubject;
    private String password;

    public EmailSender() {
        listeners = new ArrayList();
    }

    public void addListener(Listener listener) {
        listeners.add(listener);
    }

    public void removeListener(Listener listener) {
        listeners.remove(listener);
    }

    public void createEmails() {
        emailText = getNewEmailTextFromDataBase();
        emailSubject = getNewEmailTitleFromDataBase();
        password = getPasswordFromDataBase();
        notifyListeners();
    }

    public void notifyListeners() {
        for (Listener listener : listeners) {
            listener.update();
        }
    }

    // Getters and Setters
}
// Our superclass EmailPattern. All Emails patterns will extend this class
public abstract class EmailPattern implements Listener{
    protected Notifier emailSender;

    public EmailPattern(Notifier emailSender){
        this.emailSender = emailSender;
    }

    public void update(){
        collectData();
        sendEmail();
    }

    protected abstract void collectData();
    protected abstract void sendEmail();
}
// This is our implementation. The class will get the password and any other data that it needs
public class YahooPattern extends EmailPattern {
    private String emailText;
    private String emailSubject;
    private String emailPassword;

    public YahooPattern(Notifier emailSender) {
        super(emailSender);
    }

    @Override
    protected void collectData() {
        emailText = emailSender.getEmailText();
        emailSubject = emailSender.getEmailSubject();
        emailPassword = emailSender.getPassword();
    }

    @Override
    public void sendEmail() {
        System.out.println("Sending email subject: " + emailSubject + " with the text: " + emailText + " with the password: " + emailPassword);
    }
}

Com isso, podemos chegar a mais um princípio de Design:
"Procure sempre diminuir o acoplamento em objetos que se comuniquem."
Nós realizamos esse desacoplamento ao simplesmente fazer com que nossa classe Notifier possa fornecer dados, mas não entender o que cada Listener necessita. Ela apenas coleta todos os dados e chama cada Listener, e o Listener por sua vez é quem sabe qual informação utilizar.

Um resumo do visto até hoje:
Padrão de Projeto: Strategy
Princípios vistos:

  • Identifique tudo o que varia e separe do restante que não irá variar.
  • Programe para interface.
  • Dar prioridade à composição.

Padrão de Projeto: Observer
Princípios vistos:

  • Procure sempre diminuir o acoplamento em objetos que se comuniquem.


Qualquer dúvida/colocação basta escrever.

Espero que você goste, até a próxima.

Revisado por: Renan Alves dos Santos

Leave a Comment