Creating a lambda handler function which can resolve an extra parameter to the handler. This works but has some quirks I don't like. I'm currently using this approach.
Cosa non ti piace? Mantenendo la firma piccola e permettendo al gestore di essere a conoscenza delle cose che ha (ma l'oggetto che lancia eventi ha bisogno di non sapere) si separa molto efficacemente la conoscenza da dove deve andare.
I could couple the QuestLog to a Player, passing a reference of the player it belongs to in and fire events off accordingly with it. Feels like needless coupling.
Dato che i giocatori hanno già QuestLogs, allora direi che l'accoppiamento esiste già in una certa misura. Inoltre, se il tuo gestore vuole saperlo, questo non fa altro che rafforzare questa nozione.
L'accoppiamento non è sempre cattivo. Alcune cose dovrebbero davvero dipendere l'una dall'altra e un design pulito accoppierà queste cose insieme in modo coerente, in modo che sia semplice, pulito e robusto.
Expose the event on the Player object itself as well as the QuestLog and 'bubble' the event up into where the context is available, thus allowing subscriptions directly onto player.
A volte buono, ma spesso un segno che hai l'evento nel posto sbagliato. Questo fa trapelare dettagli di implementazione (o almeno lo sarebbe se non avessi QuestLog sul lettore pubblicamente, incoraggiando gli utenti a violare la legge di Demeter ...).
Ma tornando al mio commento, gli eventi si sono in gran parte disinnescati dal fare logica non UI. Gli eventi, per loro natura, causano un accoppiamento temporale (devi fare le cose nel momento giusto, nell'ordine giusto perché funzionino correttamente). Gli eventi proteggono gli invarianti in modo scadente e tendono a filtrare attraverso le astrazioni. Sono fragili, sono abbastanza difficili da testare, richiedono un mediatore per aggiungere / rimuovere l'evento, sono la causa principale delle perdite di memoria ...
Più spesso, i delegati (o le dipendenze stesse) vengono passati direttamente al costruttore in modo che il gestore sia conosciuto in fase di costruzione. Non si può abusare della classe se è costruita per funzionare sin dall'inizio.
Questo o cose funzionano su un meccanismo di pull piuttosto che di push. Qualcosa controlla lo stato ogni frame o qualche altro intervallo temporale (opzionalmente controllando un flag sporco che viene premuto). Ciò rende più facile ignorare i tempi delle cose in molti casi, rendendo il parallelismo molto più praticabile.