Pattern osservatore: impedisce più attivazioni sulla proprietà interna modificata

1

Ho un oggetto Foo che ha 2 proprietà pubbliche: A e B .

Queste proprietà possono essere modificate dall'esterno, poiché l'applicazione su cui sto lavorando utilizza un'architettura di associazione dei dati. Questo è il codice front-end (client), ma comunica anche con un server per recuperare i dati.

Quindi il mio oggetto sta ascoltando le modifiche sia a A che a B .

Qualsiasi modifica in A o B sta attivando il metodo update() , che attiva una richiesta al server.

Ho anche un pezzo di logica nel mio oggetto Foo che dice ogni volta che cambi B , devi resettare A al suo valore iniziale.

Il mio problema è, come faccio a gestire l'aggiornamento di B senza attivare il metodo update() due volte?

Guardando l'immagine sopra, il percorso verde dovrebbe sempre attivare un aggiornamento. Il percorso rosso termina a volte attivando 2 aggiornamenti, perché cambiando B cambia A (se non è il valore iniziale), che attiva sempre un aggiornamento.

Devo aggiungere che tutto è asincrono quindi gli osservatori per le mie proprietà non mi notificano immediatamente dopo aver cambiato gli oggetti. (Scelta progettuale della piattaforma e della lingua in cui lavoro - Polymer.JS). Quindi questo rende più difficile impostare un flag prima di cambiare B da A - Ho provato a farlo ma non ha funzionato, poiché il metodo watcher viene attivato dopo l'esecuzione della catena di modifiche.

Come vengo dal mondo front-end, con un background in graphic design, non ho le conoscenze necessarie per individuare gli errori che potrei fare, ma voglio imparare, quindi mi piacerebbe che tu Indicami come riferimento materiale e / o libri che posso leggere sulle corrette applicazioni del modello di osservatore.

C'è uno schema che si occupa di questo particolare scenario e quali sono le possibili soluzioni a questo?

Se il pattern dell'osservatore non è la scelta giusta per questo, c'è un altro pattern che potrei usare internamente che mi permetta di esporre solo le due proprietà A e B al mondo esterno?

Una terza opzione sarebbe che sto applicando il modello giusto, ma la piattaforma non supporta ciò che sto cercando di ottenere. Mi piacerebbe saperlo, così posso pubblicare la domanda su StackOverflow sotto i tag giusti.

    
posta Cristian 26.02.2015 - 09:14
fonte

2 risposte

2

Si fa un messaggio speciale ad A che lo modifica in un modo non propagato. È un linguaggio comune in cui si desidera che gli aggiornamenti generali inviino notifiche, ma non aggiornamenti interni o aggiornamenti.

Ad esempio, ho una finestra di dialogo con gestori di notifiche per le modifiche ai vari controlli, ma nell'inizializzazione voglio impostare lo stato iniziale dei controlli - senza inviare queste notifiche. In questo caso, ho semplicemente impostato un flag di 'inizializzazione' che il gestore di notifiche controlla, se il suo set non fa semplicemente il gestore.

Se non è possibile impostare un flag per modificare lo stato di A per impedire la notifica, è necessario inviarlo con il messaggio di modifica. Quindi hai 2 messaggi, uno per aggiornare A (il caso generale) e l'altro per cambiare A in modo silenzioso, che viene inviato da B, ma consente comunque di attivare le modifiche ad A quando altri lo cambiano. Non so come si apportano questi aggiornamenti, quindi le specifiche di implementazione dipendono da voi.

    
risposta data 26.02.2015 - 09:41
fonte
1

Generalmente i valori A e B sono nascosti usando un mixin, modificabile solo attraverso un metodo setA e setB (o meglio ancora usando un setter funzione). Internamente, devi semplicemente assegnare A o B direttamente senza chiamare direttamente setA o setB, quindi chiamare update () che attiva l'evento.

In altre parole, avresti impostato A che assegna A e quindi ripristina il valore di B senza chiamare setB. Dai un'occhiata a questo rapido esempio:

function Obj() {
  var A, B;

  function resetB() {
    console.log('Resetting B');
    B = '';
  }
  function update() {
    console.log('Values updated');
  }
  return {
    get A() { return A; },
    get B() { return B; },
    set A(aVal) { 
      A = aVal; 
      resetB(); 
      update();
    },
    set B(bVal) { 
      B = bVal;
      update(); 
    }
  };
}
var obj = new Obj();
obj.B = 'test';
// Console output:
// Values updated

// assert(obj.B == 'test')
obj.A = 'me';
// Console output:
// Resetting B
// Values updated

// assert(obj.A == 'me')
// assert(obj.B == '')
    
risposta data 26.02.2015 - 12:12
fonte