Design Pattern – Observer (Part 02)

Hello, how are you?

Let us keep talking about the Observer pattern. If you did not read the first post about this pattern, read it before reading the Part 2 about this pattern (Design Pattern – Observer (Part 01) ).

How could we loose coupling of our classes? (Questioning of the last post Design Pattern – Observer (Part 01) )

A good way to loose this coupling would be: the class Listener receives a reference to its Notifier class. It is a very simple solution.

Our Notifier class will only “tell” to a Listener that something happen through the “update” method, and the Listener will decide which attributes will be needed.

The class YahooPattern will need a password to send the email, it will access the Notifier the get this information. Let us begin the refactoring?

First of all we need to refactor the “update” method. Let us use another kind of super class? Let us update our UML and use an abstract super class (instead interface like we did in the last post).
Design Pattern - Observer (Part 02)Design Pattern - Observer (Part 02)
We updated our interface Notifier, now it has methods that will be visible to our listeners. The listeners now will be able to get the information that it is needed to send an email. The class that sends the email (EmailPattern) has a reference to the Notifier.

The Notifier reference will enable the emailSender to get all the needed data, instead the older version where the Notifier has the responsibility to know each of its listeners. If each listener change the needed parameters to send an email, the update method from the Notifier class will remain intact. If you had to change any email class to get another data, you only need to change the “collectData” method that is an abstract method which every subclass will implement.

If a new requirement comes to the HotmailPattern class, like add a specific image to the text, you would need to add the get method to the Notifier interface and update the HotmailPattern class to get and use this value. Notice that our class Notifier has been changed by adding a get method only, and the Notifier does not need to know whom/how will use this data.

Let us see our implemented code:

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);
    }
}

And here comes a new Design principle:
“Always try to loose the coupling between classes that communicates.”
We loose the coupling when we updated our Notifier class to only provide the information, instead of knowing the need of each listener; now our Notifier just calls the listeners without worrying which parameters it should pass. And by updating the listener so it might be able to collect all the data it needs.

A briefing of the design patterns seen so far:

    Design Pattern: Strategy
    Studied Principles:

  • Identify everything that changes and isolate it from what does not change.
  • Program to an interface.
  • Give priority to composition rather than inheritance.

Design Pattern: Observer
Studied Principles:

  • Always try to loose the coupling between classes that communicates.

If you have any doubt or question, just ask.

I hope you liked this post, see you soon.

2 thoughts on “Design Pattern – Observer (Part 02)

    • Hello Nyamath, how are you?

      I am sorry for the late reply, I have been really busy this last month.

      Thanks for your support, I appreciate it.

      Regards

Leave a Comment