No puedo encontrar una mejor solución a mi problema. Tengo un controlador de vista que presenta una lista de elementos. Esos elementos son modelos que pueden ser una instancia de B, C, D, etc. y heredar de A. Por lo tanto, en ese controlador de vista, cada elemento debe ir a una pantalla diferente de la aplicación y pasar algunos datos cuando el usuario selecciona uno de ellos . Las dos alternativas que se me ocurren son (ignore la sintaxis, no es un lenguaje específico)
1) cambiar (sé que apesta)
//inside the view controller
void onClickItem(int index) {
A a = items.get(index);
switch(a.type) {
case b:
B b = (B)a;
go to screen X;
x.v1 = b.v1; // fill X with b data
x.v2 = b.v2;
case c:
go to screen Y;
etc...
}
}
2) polimorfismo
//inside the view controller
void onClickItem(int index) {
A a = items.get(index);
Screen s = new (a.getDestinationScreen()); //ignore the syntax
s.v1 = a.v1; // fill s with information about A
s.v2 = a.v2;
show(s);
}
//inside B
Class getDestinationScreen(void) {
return Class(X);
}
//inside C
Class getDestinationScreen(void) {
return Class(Y);
}
Mi problema con la solución 2 es que, dado que B, C, D, etc.son modelos, no deberían saber sobre cosas relacionadas con la vista. ¿O deberían en ese caso?
fuente
Más un comentario que una respuesta, pero creo que es una sacudida. O bien, la Vista tiene que saber todo sobre el Modelo para poder elegir la pantalla (interruptor) o el Modelo debe saber todo sobre la Vista para que pueda elegir la pantalla (polimorfismo). Creo que tienes que elegir lo que creas que será el más simple con el tiempo; No hay una respuesta correcta a la pregunta. (Espero que alguien pueda demostrar que estoy equivocado). Me inclino por el polimorfismo, yo mismo.
Me encuentro con este problema un poco. El caso más molesto fue una clase Wanderer, cuyas instancias deambularon por un mapa. Para dibujarlo, la pantalla necesitaba saber sobre Wanderer o Wanderer necesitaba saber sobre la pantalla. El problema era que había dos pantallas (con más en camino). Como el número de diferentes subclases de Wanderer era grande y creciente, puse el código de dibujo en las subclases de Wanderer. Eso significaba que cada clase grande tenía exactamente un método que necesitaba saber sobre Graphics2D y exactamente un método que necesitaba saber sobre Java3D. Feo.
Terminé dividiendo la clase, dándome dos estructuras de clase paralelas. La clase Wanderer se liberó de conocer los gráficos, pero la clase DrawWanderer aún necesitaba saber más sobre Wanderer de lo que era decente y necesitaba saber sobre dos (y tal vez más) entornos gráficos completamente diferentes (Vistas). (Supongo que esta idea de dividir la clase podría ser una especie de respuesta, pero todo lo que realmente hace es contener un poco el problema).
Creo que este es un problema muy general y fundamental del diseño orientado a objetos.
fuente
Creo que ir con el interruptor es una mejor opción que ir con polimorfismo para este caso.
Es algo bastante simple de hacer, así que no creo que deba complicarse demasiado mediante el uso de polimorfismo.
Me gustaría acuñar en esta publicación de blog . Las declaraciones de cambio no son necesariamente feas siempre que las use correctamente. Y en su caso, los modelos de abstracción como ese para su uso en un controlador pueden ser excesivos y producir resultados no deseados. Como violar el SRP.
fuente
Estoy de acuerdo con esta preocupación. También me preocupa un poco que los objetos que se encuentran en un cuadro combinado tengan un comportamiento. No estoy seguro de que sea una "cosa mala" que nunca lo haya hecho, simplemente me parece una elección antinatural.
Además, no parece
A
y sus subclases son del tipo con el que tienes un polimorfismo interesante. El tipo interesante es en realidadScreen
. En este ejemplo,A
es solo una clase que contiene información para informar laScreen
creación.Si hace que el cuadro combinado contenga una lista de lo que sea que
a.type
devuelva, una declaración de cambio parece más natural. Sin embargo, en lugar de ponerlo en el controlador de eventos de clic, lo pondría en unScreenFactory
. Entonces tiene:Esto le permite probar el comportamiento de creación de pantalla y extrae de forma agradable algunas funciones de su interfaz de usuario. Mantiene sus capas de Vista intactas. Quizás simplifique su diseño, si eso significa,
A
y las subclases pueden colapsarse en latype
bandera que contienen.fuente