Una tarea en mi clase de ingeniería de software es diseñar una aplicación que pueda jugar diferentes formas en un juego en particular. El juego en cuestión es Mancala, algunos de estos juegos se llaman Wari o Kalah. Estos juegos difieren en algunos aspectos, pero para mi pregunta solo es importante saber que los juegos podrían diferir en lo siguiente:
- La forma en que se maneja el resultado de un movimiento
- La forma en que se determina el final del juego
- La forma en que se determina el ganador
Lo primero que se me ocurrió al diseñar esto fue usar el patrón de estrategia, tengo una variación en los algoritmos (las reglas reales del juego). El diseño podría verse así:

Entonces pensé para mí mismo que en el juego de Mancala y Wari la forma en que se determina el ganador es exactamente la misma y el código se duplicaría. No creo que esto sea, por definición, una violación de la 'regla única, un lugar' o el principio DRY, ya que un cambio en las reglas para Mancala no significaría automáticamente que esa regla deba cambiarse también en Wari. Sin embargo, por los comentarios que recibí de mi profesor, tuve la impresión de encontrar un diseño diferente.
Entonces se me ocurrió esto:

Cada juego (Mancala, Wari, Kalah, ...) solo tendría un atributo del tipo de interfaz de cada regla, es decir, WinnerDeterminery si hay una versión de Mancala 2.0 que sea igual a Mancala 1.0, excepto cómo se determina el ganador, puede usa las versiones de Mancala.
Creo que la implementación de estas reglas como patrón de estrategia es ciertamente válida. Pero el verdadero problema viene cuando quiero diseñarlo más.
Al leer sobre el patrón de método de plantilla, inmediatamente pensé que podría aplicarse a este problema. Las acciones que se realizan cuando un usuario realiza un movimiento son siempre las mismas y en el mismo orden, a saber:
- depositar piedras en los agujeros (esto es lo mismo para todos los juegos, por lo que se implementaría en el método de la plantilla en sí)
- determinar el resultado del movimiento
- determinar si el juego ha terminado debido al movimiento anterior
- si el juego ha terminado, determina quién ganó
Esos tres últimos pasos están todos en mi patrón de estrategia descrito anteriormente. Tengo muchos problemas para combinar estos dos. Una posible solución que encontré sería abandonar el patrón de estrategia y hacer lo siguiente:

¿Realmente no veo la diferencia de diseño entre el patrón de estrategia y esto? Pero estoy seguro de que necesito usar un método de plantilla (aunque estaba tan seguro de tener que usar un patrón de estrategia).
Tampoco puedo determinar quién sería responsable de crear el TurnTemplateobjeto, mientras que con el patrón de estrategia siento que tengo familias de objetos (las tres reglas) que podría crear fácilmente usando un patrón de fábrica abstracto. Entonces tendría una MancalaRuleFactory, WariRuleFactory, etc, y que crearían las instancias correctas de las reglas y la mano ME volver un RuleSetobjeto.
Digamos que uso el patrón de estrategia + fábrica abstracta y tengo un RuleSetobjeto que tiene algoritmos para las tres reglas. La única forma en que siento que todavía puedo usar el patrón de método de plantilla con esto es pasar este RuleSetobjeto a mi TurnTemplate. El "problema" que luego surge es que nunca necesitaría mis implementaciones concretas de TurnTemplate, estas clases se volverían obsoletas. En mis métodos protegidos en el TurnTemplatesolo podría llamar ruleSet.determineWinner(). Como consecuencia, la TurnTemplateclase ya no sería abstracta, sino que tendría que volverse concreta, ¿sigue siendo un patrón de método de plantilla?
Para resumir, ¿estoy pensando de la manera correcta o me estoy perdiendo algo fácil? Si estoy en el camino correcto, ¿cómo combino un patrón de estrategia y un patrón de método de plantilla?