Quando si implementa il pattern Observer, ci sono due approcci principali da considerare: il modello "push" e il modello "pull".
Nel modello "push", il soggetto (cioè l'Osservabile) invia all'osservatore, alla notifica, tutti i dati di cui avrà bisogno. L'osservatore non ha bisogno di interrogare l'argomento per informazioni. Nel modello "pull", il soggetto si limita a segnalare all'osservatore che qualcosa è successo e l'osservatore interroga l'argomento in base alle informazioni di cui ha bisogno.
Discutiamo dei pro e contro di entrambi gli approcci:
Push
Il vantaggio principale del modello "push" è l'accoppiamento più basso tra l'osservatore e il soggetto. L'osservatore non ha bisogno di sapere nulla sull'argomento per poterlo interrogare. Se fosse necessario, avremmo bisogno di fare una delle seguenti cose: A- fare downcasting sul lato dell'osservatore per invocare metodi get
specifici della classe sull'argomento. Questo non va bene. B- Rendi l'interfaccia Observable
più specifica della classe, offrendo specifici metodi di get
, rendendo così la relazione tra l'osservatore e il soggetto meno generale e rendendo le cose più copuple.
Implementando il modello 'push', evitiamo tutto questo.
Tuttavia lo svantaggio è meno flessibilità: il soggetto può non sapere sempre quali sono le informazioni esatte di cui gli osservatori hanno bisogno per inviarle. Ciò significa spesso più specifici intefaccia di Observer, come AgeObserver
che viene notificato quando viene modificata l''età' del soggetto e HeightObserver
a cui viene inviato il height
attuale dell'oggetto alla notifica.
Questa è un'opzione. L'altro è il soggetto che invia un sacco di informazioni incapsulate in un oggetto Info
di qualche tipo e gli osservatori lo interrogano da lì. Ma ancora una volta, non possiamo essere sicuri che stiamo inviando le informazioni corrette. Quindi è questo o costringe gli osservatori a implementare interfacce Observer più specifiche, che stringono l'accoppiamento dal lato dell'osservatore.
Tirare
Ho già notato gli svantaggi del modello "pull". Gli osservatori dovrebbero conoscere le cose sull'argomento al fine di interrogare le giuste informazioni, che portano A- a downcasting (brutto), o B- favorevolmente a più specifiche Observable
interfacce, che offrono metodi di accesso più specifici. Ad esempio AgeObservable
offre un metodo getAge()
.
Il vantaggio di questo è maggiore flessibilità. Ogni osservatore può decidere da solo su cosa interrogare, senza affidarsi all'argomento per inviare le informazioni corrette.
Devi scegliere la strategia migliore per il progetto specifico su cui stai lavorando.
In realtà, avrai sempre specifiche Observer
e Observable
intefacce, quindi avrai comunque un accoppiamento tra i lati.
Quindi scegli "tira" o "spingi" con ciò che ti sta meglio.
Tutta la AgeObserver
s ha bisogno semplicemente del age
del soggetto? Implementare il modello 'push'. Meno accoppiamento e più semplice.
Tutte le HeightObserver
s hanno bisogno di informazioni variabili sull'argomento - anche se è necessario interrogare l'età e qualche altro oggetto deve interrogare il peso oltre all'altezza? Implementa il modello "pull". Questo ti costringerebbe ad aggiungere accessors (getter) al Observable
inteface (o questo o passare l'oggetto reale come parametro nel suo tipo esplicito, ma farlo attraverso l'interfaccia ti permette di negare agli osservatori l'accesso a cose che don ' t importa a loro). Questa anima crea un accoppiamento più elevato, ma è più flessibile.
Scegli quello che si adatta meglio alla tua situazione.