28

Sto cercando di progettare un quadro asincrona e voleva sapere cosa pensa la gente sono i vantaggi/svantaggi del modello di callback contro il pattern Observer.Richiamata/Comando vs EventListener/Observer modello

Callback pattern: 

//example callback 
public interface Callback{ 
    public void notify(MethodResult result); 
} 

//example method 
public class Worker{ 
    public void doAsyncWork(Callback callback){ 
    //do work 
    callback.notify(result); 
    } 
} 

//example observer pattern 
public interface EventListener{ 
    public void notify(MethodResult result); 

} 

public class Worker{ 
    private EventListener listener; 
    public registerEventListener(EventListener listener){ 
    this.listener=listener; 
    } 
    public void doAsyncWork(){ 
    //do work 
    listener.notify(result); 
    } 
} 

Sto lavorando con un framework che sembra utilizzare entrambi questi modelli. Il pattern EventListener non è il modello tipico in quanto non ha un elenco di listener. Questo può essere facilmente implementato anche creando un CompositeListener che ha i suoi semantica sulla priorità di ascoltatori e come gestire la distribuzione degli eventi per ciascun ascoltatore esempio generazione di un nuovo thread per ogni listener vs notifiche seriali. (In realtà che questa è una buona idea come una buona separazione delle preoccupazioni ed è un miglioramento rispetto al osservatore/ascoltatore modello standard).

Ogni pensiero su quando si dovrebbe utilizzare ciascuno?

Thxs.

+0

Per semplificare il callback, si consiglia di utilizzare le funzioni di prima classe. quindi è solo "public void doAsyncWork (Funzione callback)' – Raynos

+0

Sono nuovo in entrambi i modelli di progettazione e mi sono confuso molto con gli esempi di codice. Sei sicuro che questi siano la demo corretta di questi due pattern, in particolare il pattern Observer? Per me, il modo in cui li hai scritti non fa differenza. Non fraintendermi però. Apprezzo sinceramente la tua domanda dal momento che ho in mente la stessa cosa. Voglio solo tirarlo fuori. Grazie! – jiu9x9uij

risposta

22

Entrambi i modelli sono grandi e quale scegliere dipende da cosa hai intenzione di costruire e come il vostro quadro verrà utilizzato.

Se si sta tentando di costruire una sorta di publish-subscribe sistema con i seguenti tipico flusso di lavoro:

  • client avvia operazione asincrona e dimentica a questo proposito
  • più gestori riceve le notifiche quando compito è completato

quindi il modello Observer è una scelta naturale per voi. Come si sta facendo un quadro si dovrebbe anche considerare l'utilizzo di EventBus modello per realizzare accoppiamento lasco.

Se avete bisogno di niente di più che una semplice esecuzione asincrona e un flusso tipico utilizzando del framework è:

  • compito inizio asincrona
  • fare qualcosa quando è completato

o

  • start async task
  • fare qualcosa
  • aspettare che sia completato e fare qualcosa

allora si dovrebbe andare con una semplice Callback.

Ma per ottenere API più utilizzabili e pulite, ti consiglio di eliminare l'astrazione Callback e di progettare il codice del tuo lavoratore per restituire una sorta di Future.

public interface Worker<T> { 

    Future<T> doAsync(); 

} 

E Worker può essere utilizzato come segue:

Future<Integer> future = worker.doAsync(); 

// some work here 

Integer result = future.get(); // waits till async work is done 

Future potrebbe essere uno standard java Future. Ma ti suggerisco di usare ListenableFuture dalla libreria guava.

5

direi che il modello di callback è migliore in quanto è più semplice che significa che sarà più prevedibile e meno probabilità di avere bug a causa di essa il proprio stato mutazione. Un esempio di questa operazione potrebbe essere the way GWT handles browser/server communication.

Si potrebbe desiderare di utilizzare farmaci generici però:

//example callback 
public interface Callback<T> { 
    public void notify(T result); 
} 

//example method 
public class Worker{ 
    public void doAsyncWork(Callback<SomeTypeOrOther> callback){ 
    //do work 
    callback.notify(result); 
    } 
} 
25

Command, callback e osservatori modelli hanno una semantica diversa:

  • callback - Notifica un singolo chiamante che qualche operazione terminata con qualche risultato
  • osservatore - Notifica zero a parti n interessate che alcuni evento (ad esempio un'operazione conclusa) è accaduto
  • comando - incapsula una chiamata di operazione in un oggetto rendendolo così trasferibile su un filo o persistono-grado

Nel vostro esempio si potrebbe combinare entrambi i modelli di callback e osservatori per ottenere una maggiore flessibilità API:

  1. Utilizzare il modello callback per attivare le operazioni e informare il chiamante in modo asincrono che l'operazione innescata è finita.
  2. Utilizzare il modello evento/osservatore per fornire altri componenti (che hanno fatto non attivano l'operazione) la possibilità di essere avvisati al termine di un'operazione.
+1

Il punto chiave qui è: - utilizzare la richiamata per notificare al trigger - utilizzare gli eventi di incendio per notificare gli osservatori, che in questo caso non avrebbero attivato l'evento. – metakungfu

+1

La spiegazione delle differenze tra tre modelli è utile per me. – Sentimental

Problemi correlati