Questa variante di Observer è un miglioramento?

1

In una base di codice C ++ su cui sto lavorando, hanno un sacco di esempi del pattern di osservatore, ma è un po 'diverso dal modello classico. Nel classico, l'Observer è un'interfaccia specifica con uno o più metodi specifici chiamati quando l'Observable cambia o ha nuovi dati.

Observable                       Observer
register( Observer* )            update( data1, data2 ... )

Nel nostro codice base, usiamo una classe template che prende il numero e il tipo di argomenti per il metodo update () come parametri e consente di specificare qualsiasi puntatore-metodo come destinatario dei dati.

Observable                          
register( Functor<data1, data2> )   

Questo è un miglioramento rispetto al modello originale? Ecco cosa penso siano i pro di ciascun approccio:

Classico:

  • chiarezza - l'interfaccia indica quali classi sono destinatari di dati osservabili
  • less code - la piastra della caldaia e la brutta sintassi del template per creare il functor sono piuttosto onerosi

Variante:

  • flessibilità: posso far sì che qualsiasi oggetto nel mio sistema riceva l'aggiornamento (se ha la firma del metodo corretta) senza dover cambiare l'oggetto originale

Come altra opzione, ho tutto sbagliato che questo è lo schema di Osservatore in pratica?

    
posta Sesquipedalian 19.02.2013 - 14:02
fonte

3 risposte

5

La tua idea è stata già inventata 10 anni fa da Herb Sutter. Vedi questo articolo: link , contiene una spiegazione completa.

Quindi la risposta è

  • sì, è un miglioramento rispetto alla variante GOF originale del pattern

  • no, non è migliore di ogni altra implementazione nota del pattern Observer

Nota anche che ciò che hai suggerito qui è "l'implementazione dell'osservatore standard" in linguaggi o linguaggi funzionali con elementi funzionali in cui gli eventi / sink di eventi sono in genere implementati in modo comparabile (ad esempio in C # usando delegati).

    
risposta data 19.02.2013 - 14:36
fonte
1

Solo per verificare, sai che il tuo Functor è solo std::function , giusto?

In secondo luogo, è assolutamente meglio. È possibile registrare lambdas, oggetti funzione, ecc., Quindi è molto più flessibile di richiedere la derivazione e non è necessario definire dieci miliardi di interfacce, ognuna delle quali è dupes l'una dall'altra.

    
risposta data 19.02.2013 - 14:34
fonte
1

Ho implementato molte varianti del pattern Observer in C ++ e una cosa che ho imparato è che non esiste un modo generico di farlo sfortunatamente, un po 'come provare a creare un compilatore unico.

Dipende dalle funzionalità necessarie per l'utilizzo specifico. Una caratteristica importante che è o non è richiesta è la disconnessione.

Disconnettere un osservatore richiede che possiamo identificare l'osservatore da disconnettere. Ci sono diversi modi per farlo. Boost.Signals (2) fai questo fornendo un oggetto che è fondamentalmente un handle per la connessione e può essere usato per disconnetterti.

Il tuo primo esempio consente la disconnessione, in quanto possiamo identificare un osservatore confrontando i puntatori; il secondo esempio non consente la disconnessione se Functor è std :: function < > in quanto non può essere confrontato (c'è esplicitamente nessun operatore ==).

Se il tuo Functor < > può essere confrontato correttamente, quindi è possibile disconnettersi. Se non lo è, a seconda del caso d'uso, può essere o meno un problema.

Inoltre, tieni presente che una classe Observer può essere più utile nella definizione di un insieme di messaggi che devono essere tutti gestiti dall'osservatore.

In realtà, dipende dal caso d'uso.

    
risposta data 19.02.2013 - 15:10
fonte

Leggi altre domande sui tag