Pattern di osservatore; sapendo * cosa * è cambiato?

9

Ho creato due classi astratte Soggetto e Osservatore che definiscono una classica interfaccia per modelli Observer. Io traggo da loro per implementare il modello di Osservatore. Un osservatore potrebbe apparire come questo:

void MyClass::Update(Subject *subject)
{
    if(subject == myService_)
    {
        DoSomething();
    }
    else if(subject == myOtherService_)
    {
        DoSomethingElse();
    }
}

Questo va bene e mi dice chi ha cambiato qualcosa. Tuttavia, non mi dice cosa è cambiato. A volte questo è ok perché sto solo andando a interrogare il soggetto per gli ultimi dati, ma altre volte ho bisogno di sapere cosa esattamente cambiato sull'oggetto. Ho notato che in Java hanno sia un metodo notifyObservers () che un notifyObservers (Object arg) metodo per presumibilmente specificare i dettagli su cosa è cambiato.

Nel mio caso ho bisogno di sapere se una di una coppia di azioni diverse è accaduta sull'argomento e, se si tratta di un'azione particolare, di conoscere un numero intero relativo a quell'azione.

Quindi le mie domande sono:

  1. qual è il modo C ++ per passare un argomento generico (come fa Java)?
  2. Observer è anche il modello migliore? Forse una specie di sistema di eventi?

Aggiorna

Ho trovato questo articolo che parla del modello di Observer: Implementazione di un pattern soggetto / osservatore con modelli . Questo mi ha fatto domandare se potessi definire un argomento.

Ho trovato questa domanda di overflow dello stack che parla del modello dell'argomento: Modello di osservatore soggetto basato su modello - Devo usare static_cast o dynamic_cast . Tuttavia, l'OP sembra avere un problema a cui nessuno ha risposto.

L'altra cosa che potrei fare è cambiare il metodo di aggiornamento per prendere un oggetto EventArg come in:

void MyClass::Update(Subject *subject, EventArg arg)
{
  ...

Quindi creare sottoclassi di EventArg per dati specifici sugli argomenti, quindi suppongo di ricondurli alla sottoclasse specifica all'interno del metodo di aggiornamento.

UPDATE 2

Trovato anche un articolo, Sulla creazione di un framework c ++ basato su messaggi asincroni; parte 2 in cui si discute se l'Oggetto comunica dettagli su cosa è cambiato.

Ora sto seriamente pensando di utilizzare Boost.Signals . Usare il mio schema di osservatore aveva senso quando era semplice, ma il templating del tipo e un argomento cominciavano a complicarsi. E potrei aver bisogno della sicurezza del thread di Boost.Signals2.

UPDATE 3

Ho trovato anche alcuni articoli interessanti sul modello di osservatore:

Generalizing Observer di Herb Sutter

Implementazione del pattern di osservatore in C ++ - Parte 1

Esperienze di implementazione del modello di progettazione dell'osservatore (parte 2)

Esperienze di implementazione del modello di progettazione dell'osservatore (parte 3)

Tuttavia, ho spostato la mia implementazione sull'uso di Boost.Signals che, anche se probabilmente è gonfio per i miei scopi, sta funzionando con successo. E probabilmente qualsiasi preoccupazione di aumento di velocità o di velocità è irrilevante.

    
posta User 15.12.2011 - 23:14
fonte

3 risposte

4

Se C ++ o JAVA, una notifica all'osservatore può venire insieme alle informazioni di quale è cambiato. Gli stessi metodi notifyObservers (Object arg) possono essere utilizzati anche in C ++.

Generalmente, il problema rimarrà che potrebbero esserci più soggetti che inviano a uno o più osservatori e, quindi, class arg non può essere codificato in modo rigido.

Di solito, il modo migliore per fare è creare un argomento sotto forma di messaggi generici / token che formino lo stesso tipo di dati per varie classi, ma i valori differiscono per le diverse classi osservate. In alternativa, se tutti questi valori di notifica sono derivati dalla classe su una classe base comune a tutti.

Per il pattern di osservatore, è importante che il tipo di dati Arg non sia codificato in modo rigido tra l'osservatore e l'osservatore - altrimenti è un accoppiamento che rende le cose difficili da evolvere.

Modifica
Se vuoi che l'osservatore non solo osservi, ma abbia anche bisogno di svolgere molte altre attività basate su che cosa è cambiato , puoi anche controllare Pattern visore . Nello schema visitatore, l'osservatore / visitatore chiama oggetto modificato e quindi non può solo sapere quale sia la modifica ma può effettivamente lavorarci sopra

    
risposta data 16.12.2011 - 06:22
fonte
0

Ci sono alcuni modi per inviare un argomento di evento generico "Java Like" in C ++.

1) Dichiara l'argomento dell'evento come void * e lo lanci alla classe giusta nel gestore di eventi.

2) Dichiara l'argomento dell'evento come un puntatore / ref a una nuova classe / interfaccia come (in risposta al tuo esempio)

class GenericEventArgument
{
  virtual bool didAction1Happen() = 0;
  virtual int getActionInteger() = 0;
};

E le classi degli argomenti degli eventi effettivi derivano da questa classe.

Per quanto riguarda la tua domanda riguardante un osservatore basato su template check out

link

    
risposta data 10.10.2016 - 11:48
fonte
-1

Non so se questo è il nome canonico, ma dai miei vecchi tempi di Smalltalk ricordo il termine "aspetto" per identificare ciò che è cambiato sull'osservabile.

Non è complesso come la tua idea di EventArg (e la sua sottoclasse); passa semplicemente una stringa (potrebbe anche essere una costante intera) dall'osservabile all'osservatore.

Inoltre: ci sono solo due metodi semplici ( update(observable) e updateAspect(observable, aspect)

Meno: l'osservatore potrebbe dover chiedere all'osservabile ulteriori informazioni (ad es. il tuo "numero intero")

    
risposta data 10.10.2016 - 11:08
fonte

Leggi altre domande sui tag