Design Pattern – Observer (Part 01)

Hello, how are you?

Today we will talk about another Design Pattern, “Observer”. If you want to see the first design pattern that we studied you can see it here (Strategy). Let us do a fast review about all design pattern subject that we have studied 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.

Let us work with the following user case:
“Mail4Usted is a company that sends emails to the clients that are recorded in its database. The company has a system that applies specifics configurations to each email server, there are a specific configurations for emails like Gmail, Hotmail.


The Mail4Usted is requesting a refactoring in its system. The problem is that the last company that was doing the maintenance of the company system has disappeared; everything that the Mail4Usted can do is to send the last version of the software code.

The system sends email only to two email servers: Gmail and Yahoo. The Mail4Usted wants its system to send email to the Hotmail customers; if the Mail4Usted likes the job new requests will be done.
Our newest customer also explains that this division for the email servers is needed because of the specific configuration that it is applied for each email server.”

The code that we received is written bellow:

public class EmailSender{
    public void sendNewEmails(){
        String emailText = getNewEmailTextFromDataBase();
        String emailSubject = getNewEmailTitleFromDataBase();

        sendEmailToGmail(emailText, emailSubject);
        sendEmailToYahoo(emailText, emailSubject);
    }

    //Others methods
}

A very simple and pour solution would be, to write the method that sends email to the Hotmail and we would be happy:

public class EmailSender{
    public void sendNewEmails(){
        String emailText = getNewEmailTextFromDataBase();
        String emailSubject = getNewEmailTitleFromDataBase();

        sendEmailToGmail(emailText, emailSubject);
        sendEmailToYahoo(emailText, emailSubject);

        // Our new method
        sendEmailToHotmail(emailText, emailSubject);
    }

    //Others methods
}

Imagine if every time that an email server had to be added or receive some maintenance in the system, our main class will be edited. Our main class would be long, hard to maintain and with none cohesion.

To make our code better we could apply two design patterns: starting with Strategy and then the Observer.

What always change in our code that we could isolate? Notice that we have a behavior that is always changing and every refactor that we have to do will affect our main class; this is something that does not need to happen.

Applying the concepts of the Strategy pattern we will isolate the behavior that always changes. But to do things more interesting, what if we understand a little bit about the Observer pattern so we might apply the two patterns together? Let us see a little history that will give us the idea of how the Observer pattern works:

“Imagine that you subscribed in a store to receive its announcements about some products with discounts. Even if you do not have any idea of when you can buy these products with discounts, you will receive the announcement.
Notice that you will be like a “target” of these notifications even if you are busy with others occupations. You will receive the announcements no matter if you are reading the news paper, watching TV or walking with the dog.”

What if we apply this “announcement” idea here? We could write the code isolating all send email behavior (Strategy). After we isolate the code that varies into a class, this class will receive like a notification informing that it already has the needed data (working like a Listener). We will be applying the Observer pattern that works like this: “The class A notifies to the class B needed information, the class B will work with this information”.

We could define the Observer pattern by:

“Defines a dependency relationship “One to Many”. When this objects state changes, all others objects with this relationship will be notified about this changing.”
To apply this concept in our user case we will use the class EmailSender to notify each class EmailHoster that a new routine to send email will be able to begin.

First let us take a look in how our interfaces will be (remember to always code to interfaces, and interfaces means a super type!):Design Pattern Observer Parte 01
With this interfaces we will have a code more flexible to refactoring, with good design patterns applied.

The Listener will be notified that some changing has happened (update(…) method) in the stated of our object “Notifier” (that it is the responsible to notify). After the object Listener receive this notification, it will send the emails (sendEmail() method).

Our classes of the type Listener and EmailPattern:Design Pattern Observer Parte 01

Our class Notifier:

Design Pattern Observer Parte 01
We have isolated all behaviors that changes (Strategy). We removed the code from the principal class, we have now a class that will send the email (EmailPattern classes); this “send email” code will be inside the class EmailPettern. We also have a class to set up the info and give to the EmailPattern classes (EmailSender).

Take a look how our classes will be coded:

public class EmailSender implements Notifier {
    private List listeners;
    private String emailText;
    private String emailSubject;

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

        notifyListeners();
    }

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

    //Others methods
}
// All classes would have almost the same implementation with their own peculiarities.
public class GmailPattern implements Listener, EmailPattern {
    public void update(String emailText, String emailSubject){
        // apply class peculiarities
        sendEmail();
    }

    public void sendEmail(){
        // send the email
    }
}

I only wrote above the code of the GmailPattern to do the reading easier. All others classes like HotmailPattern, YahooPattern would have the same methods with not equal behaviors.

You can see how cleaner our code is, with more cohesion and functional. No matter which kind of email we are working with (GmailPattern, YahooPattern or HotmailPattern), our class of the type Notifier will notify to its Listener that some changing happened in its state. Our class Notifier does not need to know anymore which kind of email server (Gmail, Yahoo, Hotmail …) it is working with. Can you see how our class EmailSender still working with the emails in a “cleaner” way?

Notice that if we need to change the method that configures the Hotmail html, our class EmailSender will not receive any edition. Isolating this behavior we are allowing our software to be more flexible to changes.

You may be thinking: “What is the advantage of the Observer pattern? Where can I apply this?” I will write some samples below:

  • Every time a car passes through a Stop light without stopping, some machine will take a picture and send it to the system. There is “somebody” that “saw” this car passing and notified to the system what happened.
  • An application that sends online messages. Let us to study some messenger: the old ICQ (but work the same with the messengers of our days) where you need to have the app in your pc. You can send a message by selecting a buddy, typing some text and sending it. The ICQ notifies the server delivering this message. Or the ICQ of your buddy will search for undelivered messages there or the server will notify the user ICQ in his PC. One thing is for sure, no matter what your buddy is doing: “reading soap opera news”, or “watching Tom & Jerry cartoons on Youtube”, he will receive this message.
  • One simpler sample to finish: a TV remote control. There is an application waiting for the stimulus that comes from the control. When you push the button the application understand the action you requested and execute it.

But we still having a strong coupling between our class EmailSender and its Listeners (GmailPattern…). Take a look at the code above and try to figure it out…

To let this coupling easier to see, let us take a look in a new user case:
“Image now that more than the subject and the email text (body text), it will necessary to inform which Yahoo account we will use. With this new user case, we will have a Listener with different behavior of the others.”
Every time we need to change the amount of parameters to send to a Listener, like YahooPattern, our Notifier (EmailSender) will have to change too.

How can we work in this coupling? The ideal is when you edit one class, this editing do not affect any other.

We will see in the next post about Design Patterns a solution to louse this coupling.

See you soon! o_

Leave a Comment