Un compito nella mia classe di ingegneria del software è quello di progettare un'applicazione che può giocare in diverse forme in un determinato gioco. Il gioco in questione è Mancala, alcuni di questi giochi sono chiamati Wari o Kalah. Questi giochi differiscono per alcuni aspetti, ma per la mia domanda è importante solo sapere che i giochi potrebbero differire nei seguenti:
- Il modo in cui viene gestito il risultato di una mossa
- Il modo in cui viene determinata la fine del gioco
- Il modo in cui viene determinato il vincitore
La prima cosa che mi è venuta in mente per progettare questo è stato usare il modello di strategia, ho una variazione negli algoritmi (le regole reali del gioco). Il design potrebbe apparire così:
Ho quindi pensato a me stesso che nel gioco di Mancala e Wari il modo in cui il vincitore è determinato è esattamente lo stesso e il codice sarebbe duplicato. Non penso che questa sia, per definizione, una violazione dell '"una regola, un posto" o del principio DRY visto che un cambiamento nelle regole per Mancala non significherebbe automaticamente che anche quella regola dovrebbe essere cambiata in Wari. Tuttavia dal feedback che ho ricevuto dal mio professore ho avuto l'impressione di trovare un design diverso.
Poi ho pensato a questo:
Ogni gioco (Mancala, Wari, Kalah, ...) avrebbe solo un attributo del tipo di interfaccia di ogni regola, vale a dire WinnerDeterminer
se c'è una versione Mancala 2.0 che è la stessa di Mancala 1.0, tranne per il modo in cui il vincitore è determinato, può solo usa le versioni di Mancala.
Penso che l'implementazione di queste regole come modello strategico sia certamente valida. Ma il vero problema arriva quando voglio progettarlo ulteriormente.
Nel leggere il modello di metodo del modello ho immediatamente pensato che potesse essere applicato a questo problema. Le azioni eseguite quando un utente effettua una mossa sono sempre le stesse e nello stesso ordine, vale a dire:
- depositare pietre nei buchi (questo è lo stesso per tutti i giochi, quindi sarebbe implementato nel metodo modello stesso)
- determinare il risultato della mossa
- determinare se il gioco è terminato a causa della mossa precedente
- se il gioco è finito, determinare chi ha vinto
Questi tre ultimi passaggi sono tutti nel mio modello di strategia descritto sopra. Ho molti problemi a combinare questi due. Una possibile soluzione che ho trovato sarebbe quella di abbandonare il modello di strategia e fare quanto segue:
Non vedo davvero la differenza progettuale tra il modello di strategia e questo? Ma sono certo di dover utilizzare un metodo modello (anche se ero altrettanto sicuro di dover utilizzare un modello di strategia).
Inoltre, non riesco a determinare chi sarebbe responsabile della creazione TurnTemplate
dell'oggetto, mentre con il modello di strategia sento di avere famiglie di oggetti (le tre regole) che potrei facilmente creare usando un modello di fabbrica astratto. Avrei quindi un MancalaRuleFactory
, WariRuleFactory
ecc. E avrebbero creato le istanze corrette delle regole e mi avrebbero restituito un RuleSet
oggetto.
Diciamo che uso la strategia + modello astratto di fabbrica e ho un RuleSet
oggetto che ha algoritmi per le tre regole in esso. L'unico modo in cui sento di poter ancora utilizzare il modello di metodo del modello con questo è passare questo RuleSet
oggetto al mio TurnTemplate
. Il "problema" che poi emerge è che non avrei mai avuto bisogno delle mie concrete implementazioni di TurnTemplate
queste classi diventerebbero obsolete. Nei miei metodi protetti nel TurnTemplate
potrei solo chiamare ruleSet.determineWinner()
. Di conseguenza, la TurnTemplate
classe non sarebbe più astratta ma dovrebbe diventare concreta, è ancora un modello di modello?
Per riassumere, sto pensando nel modo giusto o mi sto perdendo qualcosa di facile? Se sono sulla buona strada, come posso combinare un modello di strategia e un modello di metodo modello?