Estoy intentando modelar un juego de cartas en el que las cartas tienen dos conjuntos de características importantes:
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 usted podría considerar que la carta es jugable solo si puede cubrir 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;
}
Bueno, 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. Al crear 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", Ability
y Effect
tienen exactamente la misma firma.
¿Es malo tener varias interfaces con una firma idéntica? ¿Debería 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 no son idénticos (a medida que se lanzan más funciones), particularmente si son divergentes (es decir, ambos ganan algo al otro) ¿No debería, en contraposición a que solo una ganancia y la otra sea un subconjunto completo? Estoy particularmente preocupado de que combinarlos no será sostenible tan pronto como algo cambie.
La letra pequeña:
Reconozco que esta pregunta es generada por el desarrollo del juego, pero creo que es el tipo de problema que podría surgir fácilmente en el desarrollo no relacionado con el juego, especialmente cuando se trata de acomodar los modelos de negocios de múltiples clientes en una aplicación, como sucede. con casi todos los proyectos que he hecho con más de una influencia empresarial ... Además, los fragmentos de código utilizados son fragmentos de código Java, pero esto podría aplicarse fácilmente a una multitud de lenguajes orientados a objetos.