Domanda

Lavorare con un modello di callback listener tradizionale. Ho diversi ascoltatori che raccolgono varie cose. Il materiale raccolto da ogni ascoltatore è all'interno dell'ascoltatore in strutture interne.

Il problema è che desidero che alcuni ascoltatori siano a conoscenza di alcune delle "cose" negli altri ascoltatori.

Faccio rispettare l'ordine di registrazione del listener, quindi se registro consapevolmente eventi in un certo ordine un listener successivo può essere sicuro che un listener precedente abbia aggiornato i suoi contenuti e in qualche modo accedervi per fare più cose.

Il mio primo tentativo in tal senso è che ogni ascoltatore memorizzi un riferimento agli ascoltatori da cui dipende. Quindi registro gli ascoltatori nell'ordine di quelli senza dipendenze da quelli con dipendenze registrate in precedenza, e quindi stabilisco i riferimenti tra gli ascoltatori in vari metodi.

Sto cominciando a rendermi conto di quanto sia brutto e mi chiedevo se in qualche modo fosse già stato su questa strada. Quale sarebbe un modello più appropriato quando uno degli ascoltatori deve accedere alle cose in un altro?

Ecco alcuni pseudocodici per illustrare:

interface Listener { onEvent(char e); }

class A implements Listener {
  private int count;
  public void onEvent(char  e) { if(e == 'a') count++; }
  public int getCount() { return count; }
}

class B implements Listener {
 private int count;
 // private A a;
 // private void setA(A a) { this.a = a; }

 public void onEvent(char  e) { if(e == 'b') count++; }
 public int getCount() { return count; }
 public int getAPlusBCount() {
   // We know B count, but we don't know A so how would we change this 
   // so B is A aware? Or not even aware, just somehow coupled? This
   // is the question
   // return a.getCount() + count;
 }

 public void doConditionalHere() {
  // Do some condition in B that relies on the state of data in A
  int acount = 0; // a.getCount(); ???
  if(acount % 2 == 0) {
   this.count--;
  }
 }
}

class Run {
 A a = new A();
 B b = new B();
 List listeners = new List();
 listeners.add(a);
 listeners.add(b);

 // The ugly way I add coupling right now is to keep a reference to A
 // inside B. It's commented out because I am hoping there is a more intelligent approach
 // b.setA(a);

 for(char c : "ababbabab") {
   for(listener : listeners) {
     listener.onEvent(c);
   }
 }
}
È stato utile?

Soluzione

Perché non avere un oggetto centrale che terrà traccia di quante volte il metodo onEvent è stato attivato per tutte le classi di listener

 public interface CountObserver {

 public void updateCount(String className);
 public int getCount(String className);
}

public class CentralObserver implements CountObserver {

 private int aCount;
 private int bCount;

 public void updateCount(String className) {

 //There's probably a better way to do this than using
 //all these if-elses, but you'll get the idea.

  if (className.equals("AclassName")) {
   aCount++;
  }
  else if (className.equals("BclassName")) {
   bCount++;
  }
 }

 public int getCount(String className) {

  if (className.equals("AclassName")) {
   return aCount;
  }
  else if (className.equals("BclassName")) {
   return bCount;
  }
}

class A implements Listener {

 CountObserver countObserver;

 public void registerObserver (CountObserver countObserver) {

  this.countObserver = countObserver;
 }

 public void onEvent(char e) {

  if(e == 'a') {

   countObserver.updateCount (this.getClass.getName);
  }
 }

}

//Same thing for B or any other class implementing Listener. Your Listener interface should, of 

//course, have a method signature for the registerObserver method which all the listener classes 

//will implement.

class Run {

 private A a;
 private B b; 
 private CountObserver centralObserver;

 public runProgram () {

  centralObserver = new CentralObserver();
  a.registerObserver(centralObserver);
  b.registerObserver(centralObserver);

 //run OnEvent method for A a couple of times, then for B

 }

 public int getAcount () {

 return centralObserver.getCount(a.getClass.getName());
 }

 public int getBcount () {

 return centralObserver.getCount(b.getClass.getName());
 }
} 
 //To get the sum of all the counts just call getAcount + getBcount. Of course, you can always  add more listeners and more getXCount methods

Altri suggerimenti

Qui hai descritto molti accoppiamenti. La cosa migliore sarebbe eliminare tutta questa dipendenza dal canale posteriore, ma non riuscendo forse potresti avere quelle con dipendenze in ascolto non nell'elenco iniziale degli ascoltatori, ma su qualunque cosa dipendano. Oppure potresti farli aspettare fino a quando non avranno tutti i segnali.

È possibile automatizzare la gestione delle dipendenze facendo in modo che gli ascoltatori identifichino da chi dipendono. L'elenco di listener sarebbe ordinato non per ordine di inserzione, ma per assicurare che gli oggetti dipendenti seguano la loro dipendenza. L'interfaccia del tuo ascoltatore sarebbe simile a questa:

interface Listener {
  String getId();
  Collection<String> getDependencies();
  onEvent(char e);
}

O semplicemente i riferimenti, in questo modo:

interface Listener {
  Collection<Listener> getDependencies();
  onEvent(char e);
}

" Come potremmo cambiare questo in modo che Listener B sia a conoscenza di Listener A? O nemmeno consapevole, solo in qualche modo accoppiato? & Quot;

Spesso non vuoi accoppiare due " peer " oggetti come questo. Volete che due colleghi dipendano da qualcosa di comune.

La domanda più profonda è cosa fa Listener A o Listener B con tutte le informazioni che raccolgono?

Un ascoltatore fa spesso due cose: raccoglie dati e agisce. Spesso queste due cose devono essere separate. Gli ascoltatori dovrebbero ascoltare e raccogliere e fare poco di più. Alcuni altri oggetti possono essere attivati ??da un Listener.

Quello che potresti avere è solo un ascoltatore che ha diverse azioni (A e B). L'ascoltatore può quindi fornire i conteggi appropriati per A e B. Fornisce un conteggio "a" ad A. Fornisce un conteggio "a" o "b" su B.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top