Estoy intentando modelar un juego de cartas donde las cartas tienen dos conjuntos importantes de características:
El primero es un efecto. Estos son los cambios en el estado del juego que ocurren cuando juegas la carta. La interfaz para el efecto es la siguiente:
boolean isPlayable(Player p, GameState gs);
void play(Player p, GameState gs);
Y podría considerar que la carta se puede jugar si y solo si puede cumplir con su costo y todos sus efectos son jugables. Al igual que:
// in Card class
boolean isPlayable(Player p, GameState gs) {
if(p.resource < this.cost) return false;
for(Effect e : this.effects) {
if(!e.isPlayable(p,gs)) return false;
}
return true;
}
Bien, hasta ahora, bastante simple.
El otro conjunto de características en la tarjeta son habilidades. Estas habilidades son cambios en el estado del juego que puedes activar a voluntad. Cuando se me ocurrió la interfaz para estos, me di cuenta de que necesitaban un método para determinar si se pueden activar o no, y un método para implementar la activación. Termina siendo
boolean isActivatable(Player p, GameState gs);
void activate(Player p, GameState gs);
Y me doy cuenta de que, con la excepción de llamarlo "activar" en lugar de "jugar", Abilityy Effecttener exactamente la misma firma.
¿Es malo tener múltiples interfaces con una firma idéntica? ¿Debo simplemente usar uno y tener dos conjuntos de la misma interfaz? Como tal:
Set<Effect> effects;
Set<Effect> abilities;
Si es así, ¿qué pasos de refactorización debo tomar en el camino si se vuelven no idénticos (a medida que se lanzan más características), particularmente si son divergentes (es decir, ambos obtienen algo que el otro no debería, en lugar de que solo uno gane y el otro es un subconjunto completo)? Me preocupa especialmente que combinarlos no sea sostenible tan pronto como algo cambie.
La letra pequeña:
Reconozco que esta cuestión se genera por el desarrollo de juegos, pero creo que es el tipo de problema que podría surgir fácilmente en el desarrollo que no es de juegos, particularmente cuando se trata de acomodar los modelos de negocio de múltiples clientes en una aplicación como sucede con casi cada proyecto que he realizado con más de una influencia comercial ... Además, los fragmentos utilizados son fragmentos de Java, pero esto podría aplicarse fácilmente a una multitud de lenguajes orientados a objetos.