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< Observer > observers = new ArrayList< Observer >();
 
	/**
	 * 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();
	}
}