Corretto design guidato da eventi quando un consumatore si iscrive a molti produttori

1

Ho un gran numero di istanze di una classe. Quelle istanze possono sparare un evento. L'unica cosa importante per quell'evento è quale istanza l'ha licenziata.

Ho un'altra istanza di una classe (e forse in futuro più classi), che vuole iscriversi a quell'evento.

Ad esempio (in pseudo C #):

class Button
{
   public event EventHandler<Button> PressedTheButtonEvent();
}

class EventConsumer
{
   private int buttonsPressed;
   private OnButtonPressed(Button buttonReference)
   {
      buttonReference.color = blue;
      buttonsPressed++;
   }
}

Affinché la classe EventConsumer si iscriva all'evento, è necessario iscriversi al delegato EventHandler<Button> di ogni istanza. Dato che ho un gran numero di pulsanti, non mi piace iterare su tutti i pulsanti esistenti e sospendere. Questo è soggetto a errori, specialmente se, per qualche motivo, viene creato un pulsante, dopo averlo iterato su di essi.

Ho trovato 2 soluzioni:

  1. Crea PressedTheButtonEvent static.
  2. Crea un'altra classe, che ha un singolo evento. Invece di ogni pulsante che attiva il suo evento, chiama un metodo sulla nuova classe per farlo.

Non mi piace 2. perché la nuova classe è strettamente associata alla classe Button. Anche a me non piace molto 1., perché se per qualche ragione qualcuno dimentica di annullare l'iscrizione all'evento statico, quelle istanze non saranno raccolte.

Ci sono altre soluzioni?

Sto scrivendo C #, ma ho cercato di mantenere la domanda in un contesto più generale.

    
posta K. Gkinis 15.10.2016 - 01:11
fonte

2 risposte

1

2 è lo schema del mediatore.

Puoi aggirare l'accoppiamento stretto di:

  • Iniezione di un'interfaccia di IMediator con solo "pubblica" e "ascolta"

  • Usando un metodo factory per creare i pulsanti e cablare l'evento allo stesso tempo

  • Avere ButtonViewModel che prende il mediatore iniettato, l'evento e passa al ButtonView che contiene il pulsante.

Se stai facendo C # con wpf viewmodel è la strada da percorrere

    
risposta data 15.10.2016 - 14:11
fonte
1

Usa un lambda per il gestore di eventi. Il lambda acquisisce tutte le informazioni necessarie affinché funzioni al momento della sua creazione.

È come l'esempio classico della calcolatrice, in cui aggiungi pulsanti numerici in un ciclo:

for (n in 0 .. 9)
{
    let button = createNumberButton(n);
    button.Click += (source, event) => { numberButtonPressed(n); };
}

Non è necessario eseguire iterazioni su un elenco di pulsanti per la gestione degli eventi, non è necessario impostare una mappa hash di identità per le istanze, & c. :)

    
risposta data 15.10.2016 - 14:12
fonte

Leggi altre domande sui tag