Ero interessato a risolvere diversi problemi non collegati usando tecniche di ricerca di grafi generici, quindi, dopo un po 'di giocherellando, ho sviluppato il seguente schema: ogni problema implementa un'interfaccia generica "Problema" che ha uno stato iniziale e diversi metodi che prendere in stati e mosse e restituire nuovi stati e mosse. Ad esempio, posso getMoves(state)
, applyMove(state, move)
o controllare isGoal(state)
. Tutti i dettagli specifici del problema sono quindi in un unico punto e gli algoritmi generici possono passare attorno agli stati e spostarsi come "token" generici a cui non interessano realmente, utilizzando l'istanza Problema per valutare le loro proprietà. I problemi sono anche di conseguenza apolidi (o quale stato sono immutabili), il che rende il loro comportamento molto facile da ragionare.
Tutto andava bene in un sistema di tipo dinamico / anatra (JavaScript), ma nella migrazione dell'idea in un sistema di tipo statico / rigido (Java), ho riscontrato alcuni problemi.
Il problema più immediato era che questi "token" potevano davvero essere qualsiasi cosa. Array, oggetti, mappe, archi, qualunque cosa. Javascript non si è preoccupato, perché gli algoritmi li hanno semplicemente passati in giro come black-box, e i Problemi presumevano che gli avessero dato i propri token. In Java questo non è il caso. La prima soluzione più naturale è che tutti i "token" implementino un'interfaccia State
o Move
vuota. Questo ha già alcuni problemi, come se il mio stato fosse solo una struttura di dati, quindi ho bisogno di estendere o avvolgere la struttura, ma è fondamentalmente bene.
Il prossimo problema è che i token sono specifici per l'implementazione, quindi ogni volta che vengono dati al Problema, devono essere inseriti in ciò che realmente sono. Un sacco di casting mi colpisce come una bandiera rossa, quindi questo sembra un approccio cattivo (certamente spiacevole).
Per evitare tutto il casting, ho considerato brevemente qualcosa che coinvolgeva tonnellate di template (State < ChessProblem & gt ;, Move < ChessProblem >), ma sembrava un mal di testa che non avrebbe nemmeno risolto il problema.
Esiste un modo "corretto" / standard per realizzare questo in sistemi di tipo più severi? Questo è solo un cattivo schema da usare in loro (o un cattivo schema generale)? Ogni approfondimento è apprezzato. Inoltre, mentre io sono usando Java, se altre lingue statiche / severe hanno nuovi strumenti per questo genere di cose, mi piacerebbe sentirli.