2015-07-23 24 views
6

Attualmente sto utilizzando il modello Observer/Observable di Java e mi chiedevo: Perché è necessario il metodo setChanged() nella sua implementazione corrente? Capisco che è qui, quindi dobbiamo chiamare lo notifyObservers() una sola volta, alla fine del nostro trattamento.Implementazione pattern osservabile in Java

In questo modo, se vogliamo, è possibile eseguire il rollback delle modifiche con clearChanged(). Tuttavia, potremmo eseguire tutti i controlli nella nostra implementazione e chiamare solo notifyObservers() quando è assolutamente desidera aggiornare gli osservatori.

Probabilmente mi manca qualcosa, ma non capisco perché non lo abbiano semplificato in questo modo. Qualche idea?

+0

Ti stai chiedendo perché non hanno pensato che la tua implementazione avrebbe avuto una certa funzionalità e invece hai fornito tutti gli strumenti necessari per implementare le cose come volevi? –

+0

@ dave-newton Bene, detto in quel modo, la domanda sembra stupida, certo. Ma, indipendentemente da come lo fai, devi ancora implementare i controlli per stabilire se chiami clearChanged() o meno. Quindi, perché non accontentarsi di un aggiornamento ad ogni notifyObservers() e non con il flag (apparentemente superfluo) setChanged()? – Xalshin

+1

Perché potresti cambiare le cose dappertutto ma solo notificando gli osservatori una volta ogni tanto? Ad esempio, alla fine di alcune complesse logiche di business che possono o non possono chiamare 'setChanged()' in un processo a più fasi: quando è terminato, devi 'notifyObservers() 'solo se è stato modificato durante una qualsiasi delle fasi della business logic . In questo modo l'unico "cambiamento di tracciamento" che devi fare è chiamare 'setChanged()' e controllare alla fine. –

risposta

3

L'intento è quello di tenere separati i problemi separati. Gli osservatori notificanti possono essere chiamati in un posto, mentre tenere traccia dei cambiamenti avviene in un altro luogo. La maggior parte delle volte non è necessario questo tipo di separazione, ma l'implementazione java.util.Observable è stata progettata per essere in grado di gestire casi complessi, in cui non si ha necessariamente una corrispondenza 1-1 tra le modifiche e le notifiche.

Ad esempio, potrebbe essere necessario limitare le notifiche per evitare di inondare i client con eventi, che non dovrebbero influire sulle modifiche al monitoraggio man mano che si verificano. L'esempio seguente utilizza un thread di lavoro che periodicamente chiama il metodo di notifica ma che non conosce le modifiche e altro codice che accetta le modifiche ma non gestisce la notifica.

import java.util.*; 

public class ObservableExample { 

    public static void main(String[] args) throws Exception { 
     CountTracker t = new CountTracker(); 
     t.addObserver(new Observer() { 
      public void update(Observable observable, Object arg) { 
       System.out.println("observed " + arg); 
      } 
     }); 
     t.startNotifying(); 
     for (int i = 0; i < 100; i++) { 
      Thread.sleep(100L); 
      t.incrementCount(); 
     }   
     t.quitNotifying();  
     System.out.println("done");   
    } 
} 

class CountTracker extends Observable {  
    private int count = 0; 
    private Thread notificationThread; 

    public synchronized void incrementCount() { 
     count++; 
     setChanged(); 
    } 

    public synchronized void startNotifying() { 
     if (notificationThread == null || !notificationThread.isAlive()) { 
      notificationThread = new Thread(new Runnable() { 
       public void run() { 
        try { 
         while (!Thread.currentThread().isInterrupted()) { 
          Thread.sleep(1000L); 
          String event = "current value of count is " 
          + CountTracker.this.count; 
          CountTracker.this.notifyObservers(event); 
         } 
        } catch (InterruptedException e) { 
         Thread.currentThread().interrupt(); 
        } 
       } 
      }); 
      notificationThread.start(); 
     } 
    } 

    public synchronized void quitNotifying() throws InterruptedException { 
     if (notificationThread == null || !notificationThread.isAlive()) { 
      return; 
     } 
     notificationThread.interrupt(); 
     System.out.println("wait for notification thread to terminate"); 
     notificationThread.join(); 
    } 
} 

Un esempio concreto simile a questo sarebbe attua una barra di avanzamento, che richiede traducendo ingressi accumulati rappresentano compiti sempre fatto in una percentuale di completamento e decidere la frequenza di aggiornamento del display UI.

Considerare anche che è sempre possibile sottoclasse java.util.Observable. Gli sviluppatori della libreria JDK non volevano supportare un numero enorme di sottospecializzazioni delle cose, quindi preferivano creare classi il più possibile utili, ma se si desidera eliminare una ridondanza nel modo in cui si utilizza, è possibile crearne di proprie variazione.