Wzorzec Observer należy do wzorców behawioralnych, czyli takich, które kształtują zachowanie systemu. Ten model służy, zgodnie z nazwą, do obserwowania zmian stanu innego obiektu i reakcji na zmianę. Jego użycie jest konieczne, gdy potrzebujemy wykonać jakąś akcję, ale nie mamy pewności czy inny, już trwający proces np. w innym wątku już zakończył pracę, a od którego aktualności zależy nasz obiekt. Stąd wynika, że taki model wykorzystywany jest przede wszystkim w programach wielowątkowych, czy współbieżnych lub w systemach rozproszonych.

Co podglądać?

Klasycznym chyba już przykładem zastosowania tego wzorca jest automatyczny alert o pojawieniu się nowego wpisu na blogu czy nowego produktu z interesującej nas kategorii w ulubionym sklepie internetowym. Pewnym rozwiązaniem byłoby skonstruowanie mechanizmu cyklicznego odpytywania bloga czy sklepu i sprawdzanie czy pojawił się nowy wpis. Jednakże taka konstrukcja prócz prostoty ma też swoje wady tj. musimy założyć pewien interwał co który będziemy dokonywać odpytywania. Może się okazać, że zbyt częste odpytywanie skutecznie paraliżuje pracę sklepu (przy wielu odpytujących), a za rzadkie może powodować, że zbyt późno dowiemy się o nowym produkcie.

Jak podglądać?

Wpierw możemy skonstruować podstawę naszego powiadamiacza:

package wzorceprojektowe1;
/**  @author Utracki  */

interface Obserwator {
    boolean newsletter(String message);
}

Teraz już mając zaczątek możemy skonstruować klasę naszego podglądacza.

package wzorceprojektowe1;
/**  @author Utracki  */

public class ObserverService implements Obserwator{
    private String whoWatching;

    public ObserverService(String whoWatching) {
        this.whoWatching=whoWatching;
    }

    @Override
    public boolean newsletter(String message) {
        System.out.printf( "Hej %s Stało się! %s\n\r", whoWatching, message);
        return true;
    }

Nadszedł już czas aby zainstalować pluskwę w podglądanej klasie… dla symulowania prawdziwego działania nasza klasa jest wzbogacona o elementy dynamizujące.

package wzorceprojektowe1;
/**  @author Utracki  */

class Magazyn {
    private List<Obserwator> obserwatorzy;
    
  public Magazyn() {
    obserwatorzy = new ArrayList<>();
                    }
  public boolean subskrybuj(Obserwator obserwator) {
      if ( this.obserwatorzy.add(obserwator) ) return true; else return false;
  }
  
  public void symulujPrace() {
      Thread thr=new Thread(()-> {
          while (Thread.currentThread().isAlive()) {
              int wait = new Random().nextInt(1000);
              try { Thread.sleep(wait);
              } catch (InterruptedException e) { e.printStackTrace(); }
              
          
          for(Obserwator obserwator: obserwatorzy) { obserwator.newsletter("wiadomość");}
          }
      } ); 
      thr.start();
  }
}

Na koniec pozostało już tylko pokazać jak użyć powyższej struktury…

 public static void main(String[] args) {
    Magazyn obs = new Magazyn();
    obs.subskrybuj(new ObserverService("Tomek"));
    obs.subskrybuj(new ObserverService("Wojtek"));
    obs.subskrybuj(new ObserverService("Marek"));
    obs.symulujPrace();
 }

Zadanie: Przygotuj program bloga, gdzie będziesz mógł tworzyć nowe wiadomości z wpisów “dziennych”. Następnie użyj wzorca Obserwatora by stworzyć alertowanie subskrybentów o nowych wpisach.