Comunicazione tra componenti / oggetti non correlati

0

Immagina di avere un gioco, con Mostri, Missioni, Veicoli e, naturalmente, i loro controllori e così, quindi una classe Monster, una classe Mission Controller, una classe Vehicle Controller e così via.

Supponiamo che io abbia bisogno del controller di missione per parlare con i mostri. Perché? Diciamo che quando viene attivata la Missione A, tutti i Mostri ora diventano blu, dal loro colore originale.

Ci sono molti modi per far dialogare il Mission Controller con la classe Monster. Un modo è usare il pattern Observer. Il MissionController aggiungerebbe il Mostro alla sua lista di osservatori, e quando il MissionController cambia Missioni, dice al Mostro usando ONMISSIONCHANGED () o qualcosa del genere.

Il problema con questo approccio è il motivo per cui il Monster dovrebbe interessarsi a MissionController? Monster non dovrebbe nemmeno sapere che esiste MissionController? Supponiamo che un giorno non vogliamo che il mostro cambi colore, vogliamo che i veicoli lo facciano, quindi dobbiamo sbarazzarci dei mostri dalla lista degli osservatori, reimplementare la stessa cosa in Veicoli e aggiungere veicoli all'elenco, non è noioso?

Un altro approccio è usare Singletons, c'è qualche classe onnipotente che ha un puntatore a Mostri, Veicoli, qualunque cosa. E il MissionController può ottenere immediatamente un riferimento alla classe Monster. Ma i Singletons sono cattivi, e creare solo singleton per comunicare tra missioni e mostri è solo un altro trucco.

La mia domanda è allora, se il MissionController vuole impostare / ottenere una proprietà di Monster, come lo farebbe? Come posso evitare che Monster conosca MissionController, ma dì al MissionController di parlare di Monster?

TL: DR - Come si consente la comunicazione tra due oggetti completamente indipendenti, se non si desidera che si conoscano l'un l'altro, E non utilizzare il pattern Observer?

EDIT:

Quindi sembra che l'idea sia usare Mediator e messaggi, creare una classe Mediator, chiamarla MissionCommunicator, e ha una lista di osservatori in cui uno di questi sarebbe il mostro. Quando MissionController vuole parlare all'esterno, MissionCommunicator passa il messaggio all'esterno tramite l'interfaccia IMissionMessage o qualcosa del genere.

In tal caso, quindi Monster dovrebbe implementare IMissionMessage per ascoltare quel messaggio.

Ora, immagina di avere MissionController, VehicleController, AchievementController, AnimalController, eccetera .....

Supponiamo, per qualche motivo, che Monster, per lo stesso motivo per cui ha bisogno di parlare con MissionController, dovrà parlare anche con tutti quelli che lo sono.

Se lasciamo che Monster comunichi usando mediatori, ora dobbiamo fare un mediatore per Veicolo, Achievement, Animal, blahblahblah

e la classe Monster diventa questa:

Mostri classe Monster IMissionMessage, IAchievementMessage, IAnimalMessage .....

Ovviamente puoi usare l'ereditarietà dell'interfaccia per far fronte a questa situazione, crea un'interfaccia genitore IMessage che sottoclassi le interfacce IMissionMessage se stai usando Java.

Ma quale sarebbe la soluzione migliore?

    
posta Mantracker 19.11.2014 - 20:21
fonte

3 risposte

1

Nell'esempio che dai (controller di missione trasforma i mostri in blu), non avrai bisogno di comunicazione tra il controller e i mostri. Invece i mostri potrebbero cercare il "mostro di colore" in una tavolozza (o una tabella di colori). Il controller missione imposta semplicemente un valore diverso per "mostro colore" nella tavolozza quando la missione cambia. Oppure cambia l'intera tavolozza se la missione cambia non solo i mostri ...

Chiama la tavolozza su un foglio di stile e ti verrà l'idea che un cambio di missione sarà in grado di cambiare più di un semplice colore ...

Tuttavia per la tua altra domanda:

How do you allow communication between two completely unrelated objects, if you don't want them to know about each other, AND not use the Observer pattern?

Secondo me, il modo migliore per ottenerlo è tramite eventi, ad esempio nel tuo esempio:

  • i mostri sono iscritti su un canale eventi per la 'missione cambia evento '
  • il controllore emette un 'evento di cambio di missione' su canale evento e
  • i mostri cambiano colore quando ricevono l'evento 'cambio missione'

In questo modo sia il controller che i mostri non devono conoscersi l'un l'altro. Tuttavia, entrambi devono conoscere lo (stesso) "evento di cambio di missione" e lo (stesso) canale di eventi.

Per ottenere un design più disaccoppiato, puoi anche combinarlo con l'approccio alla tavolozza descritto sopra come segue:

  • un gestore di palette (o fogli di stile) è iscritto su un canale di eventi per l'evento "cambio missione"
  • il controllore emette un 'evento di cambio di missione' su canale evento e
  • il gestore passa a una tavolozza diversa (o foglio di stile) quando riceve l'evento "cambio missione"; la tavolozza viene scelta in base alle informazioni trasportate nell'evento ...
risposta data 19.11.2014 - 22:06
fonte
6

Come per tutto il design del programma, se hai due cose che non devono sapere l'una sull'altra ( A e B ) allora il design corretto è avere un mediatore C che vive sopra e che conosce entrambi:

  C
 / \
A   B

Il mediatore può quindi incollare i due insieme tramite un meccanismo di disaccoppiamento generico (eventi, messaggi, delegati, passando l'uno nell'altro, ecc.). Per i giochi, il "gioco" è solitamente qualcosa che lega i diversi componenti / moduli in una forma coesiva. Per i giochi di grandi dimensioni, di solito finisci con diversi livelli di astrazione in modo che C possa concentrarsi su due cose anziché su 90 cose.

    
risposta data 19.11.2014 - 20:36
fonte
0

Potresti usare un EventBus .

Quando si utilizza un sistema bus, i componenti dell'applicazione possono essere registrati per eventi generati da altri componenti. In questo modo un mostro potrebbe lanciare un MovedEvent o qualcosa che contiene i dati necessari.

Esistono diverse implementazioni in diverse lingue.

In java, quello usato comunemente fa parte di guava: link

Se sei serio sull'intero argomento, dovresti anche considerare l'utilizzo di un EntitySystem (supportato da un bus Event)

Vedi l'esempio di abete link per maggiori informazioni su questo.

In pratica non stai creando sottoclassi, ma componendo le tue entità di gioco. Questo lo rende piuttosto flessibile. La logica viene eseguita dai cosiddetti Sistemi e questi potrebbero comunicare tramite un EventBus.

    
risposta data 19.11.2014 - 22:22
fonte

Leggi altre domande sui tag