Z życia wzięte:

napięte terminy, ciasny czas, każdy co chwilę czegoś chce. Takie coś przeszkadza i co chwilę odrywa mnie od projektu, w końcu się lekko wkurzam i mówię „tu jest kartka, proszę zostawcie swoje telefony, jak skończę bieżący temat to zawiadomię was” … To jest przykład działania wzorca obserwatora, tak w realnym życiu.

Wzorzec obserwator pozwala na odseparowanie obiektów od siebie, w taki sposób, że mogą ze sobą współpracować, ale jednocześnie mało o sobie wiedzą. Taka luźna struktura, gdzie jeden obiekt łączy się z kilkoma w grupę jest dobra jeżeli chodzi o tworzenie elastycznych systemów oraz możliwość dynamicznej modyfikacji struktury oraz zachowania systemu.

W obserwatorze możemy wyróżnić elementy:

  • Interfejs wzorca obserwator – muszą ją implementować obiekty obserwujące
  • Obiekt obserwowany (observable, subject) – obiekt, który interesuje nas pod względem zmiany stanów
  • Obiekt obserwatora (observer, listener) – obiekty które są zainteresowane uzyskaniem informacji w przypadku zmiany stanu obiektu obserwowanego

Zalety:

  • Luźna zależność pomiędzy obiektami – obserwowany obserwator
  • Relacja pomiędzy obiektami jest dynamiczna, jest możliwa zmiana w trakcie działania aplikacji
  • Możliwość ograniczenia do korzystania z poszczególnych elementów systemu, wystarczy odłączyć danego obserwatora

Wady:

  • Możliwość zapętlenia się aplikacji w przypadku gdy jeden obserwator zmieni swój stan, a jest obserwowany przez inny obiekt, który jest obserwowany przez pierwszy obiekt. W tym przypadku grozi nam wieczna pętla i wykorzystanie 100% CPU

Przykładowa implementacja (Java):

package pl.shad.net.blog;

import java.util.ArrayList;

/**
 * Definicja interfejsu obserwatora
 */
interface Observer{
    void notifyObject();
}

/**
 * Klasa obserwowana, posiada możliwość dodania obserwatorów
 * w przypadku zmiany stanu informuje o tym
 */
class Worker{

    protected ArrayList observers = new ArrayList();

    /**
     * Dodanie obserwatora do kolejki
     * @param observer
     */
    public void addObserver(Observer observer){

        if (observer != null){
            observers.add(observer);
        }
    }

    /**
     * Usunięcie obeserwatora z kolejki
     * @param observer
     */
    public void deleteObserver(Observer observer){

        if (observer != null){
            observers.remove(observer);
        }
    }

    /**
     * Poinformowanie o zmianie stanu
     */
    public void notifyAllObject(){
        for (Observer observer : observers){
            if (observer instanceof Observer){
                observer.notifyObject();
            }
        }
    }
}

/**
 * Klasa implementująca interfej Observer
 */
class Manager implements Observer{

    private String name;

    public Manager(String name){
        this.name = name;
    }

    @Override
    public void notifyObject(){
        System.out.println("Notify object name: " + name);
    }
}

/**
 * Uruchomieniowa klasa testująca
 */
public class DesignPatternsObserver{
    public static void main(String[] args){

        //
        // Tworzenie obiektów obserwujących
        //
        System.out.println("Create object ...");
        Manager manager1 = new Manager("Manager 1");
        Manager manager2 = new Manager("Manager 2");
        Manager manager3 = new Manager("Manager 3");
        Manager manager4 = new Manager("Manager 4");

        //
        // Tworzenie obiektu obserwowanego
        //
        Worker worker = new Worker();

        //
        // Dodanie obiektów obserwowanych
        //
        System.out.println("Add observers ...");
        worker.addObserver(manager1);
        worker.addObserver(manager2);
        worker.addObserver(manager3);
        worker.addObserver(manager4);

        //
        // Wywołanie zmiany w obiekcie onserwowanym
        //
        System.out.println("\nNotify observers ...");
        worker.notifyAllObject();

        //
        // Skasowanie kilku obserwatorów i wywowłanie zmiany w obiekcie obesrowanym
        //
        System.out.println("\nDelete observers ...");
        worker.deleteObserver(manager2);
        worker.deleteObserver(manager3);
        System.out.println("\nNotify observers ...");
        worker.notifyAllObject();
    }
}