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();
}
}
Możliwość komentowania jest wyłączona.