Elegir una estrategia a través de la configuration JSON

Estoy implementando un agente de aprendizaje en Java / Kotlin. Parte de la funcionalidad de este agente implica search a través de una gran list de opciones posibles. Hay muchas maneras de search el espacio de posibilidades, y con frecuencia cambio de opinión sobre cuál es el mejor. Por lo tanto, decidí implementarlo como un patrón de estrategia.

class Agent(val searchStrategy : SearchStrategy){ fun search(input : InputGraph) : Result{ return searchStrategy.search() } } interface SearchStrategy{ fun search(input : InputGraph) : Result } class FastSearch : SearchStrategy{ //implementation here } class AccurateSearch : SearchStrategy{ // implementation here } class ExperimentalSerach : SearchStrategy{ // implentation here } 

Recientemente, he decidido ejecutar un gran set de experimentos que testingn la efectividad de varios parameters del sistema. Esto se hace a través de una secuencia de commands python, que inicia cada experimento ejecutando el file comstackdo con un file config.json diferente como argumento. Algo como:

 { "numSamples" : 5000, "environmentDifficulty" : 3, "hazardProbability" : 0.4, //etc.. } 

Ahora quiero darle al experimentador la capacidad de configurar la estrategia utilizada por el agente también. ¿Cuál es la mejor manera de hacer esto? Mi pensamiento inmediato es que podría agregar un campo de cadena adicional al config.json:

 { "numSamples" : 5000, "environmentDifficulty" : 3, "hazardProbability" : 0.4, "agentStrategy": "FastSearch" } 

Luego, contrólelo en el sistema principal con una bifurcación when o if:

 val searchStrategy = when(config.agentStrategy){ "FastSearch" -> FastSearch() "AccurateSearch" -> AccurateSearch() "ExperimentalSearch" -> ExperimentalSearch() val agent = agent(searchStrategy) 

Pero parece que empezará a volverse difícil / difícil de mantener si empiezo a agregar más estrategias. ¿Hay una mejor manera?

Una forma de resolverlo es usar el nombre de la class para cargar y crear una instancia de la estrategia como esta:

 val agentClass = classLoader.loadClass(config.agentStrategy)!! val agent = agentClass.newInstance() as SearchStrategy 

Otra forma sería registrar todas las estrategias de búsqueda y luego hacer coincidir una usando la config dada así:

 class SearchStrategies(val strategies: List<SearchStrategy>){ fun findForConfig(config:Config) = strategies.find { it.javaClass.name.contains(config.agentStrategy) } } //somewhere at boot time val searchStrategies = SearchStrategies(listOf(FastSearch(), AccurateSearch())) //when needed val config = ... val agent = searchStrategies.findForConfig(config) 

Finalmente, también es posible utilizar SPI para lograr una mayor extensibilidad y compatibilidad estándar a costa de la complejidad.

  • Propiedad observable que permite agregar observadores en time de ejecución
  • JavaRX: cómo devolver el valor en caching inmediatamente y en paralelo hacer una request de networking
  • Prueba JUnit en Kotlin
  • RecyclerView animation de elementos, se llama AnimationFinished, pero no está activado en AnimationStarted. ¿Por qué?
  • Android Studio y Kotlin: reference no resuelta: también
  • No se puede devolver el resultado factorial en la function tailrec en Kotlin
  • El procesador de anotación de Kotlin genera un error de time de compilation al usar Room con Android Studio 3.0 beta7
  • RxJava cómo agrupar elementos de una list en Map <Key, List <Value >>
  • Lista de edición de Kotlin
  • Código simplificador que son funciones idénticas excepto por la firma (varargs vs map)
  • Intellij IDEA no agrega dependencies maven a la ruta de classs de scripts de Kotlin