Estoy trabajando en una aplicación heredada de Java, que trata de "frutas" y "verduras", digamos, por el bien de la pregunta. Se tratan como cosas diferentes internamente, porque no tienen todos los métodos/propiedades en común, pero se HACEN muchas cosas muy similares a ambos.¿Cuál es el diseño adecuado para hacer frente a esto?
Por lo tanto, tenemos un montón de métodos doSomethingWithAFruit (fruta f) y doSomethingWithAVegetable (Veg v), que utilizan el correcto doOtherStuffWithAFruit (fruta f)/doOtherStuffWithAVeg (Veg v). Y esos son muy similares, excepto que los métodos que hacen cosas con frutas solo llaman a los métodos que hacen cosas con frutas, y lo mismo para las verduras.
Quiero refactorizar esto para reducir la duplicación, pero no estoy seguro de cuál es la mejor manera de lograrlo. He leído un poco sobre algunos patrones de diseño, pero no sé si me ha dejado más claro. (Puedo reconocer algunos patrones en el código que uso, pero realmente no sé cuándo debería aplicar un patrón para mejorar las cosas. Tal vez debería leer más acerca de la refactorización ...)
Estaba pensando en estas dos opciones:
1. Creando una clase que puede tener una instancia de una fruta o un vegetal y pásala a los métodos, tratando de minimizar la duplicación. Sería así:
public void doSomething(Plant p) {
// do the stuff that is common, and then...
if (p.hasFruit()) {
doThingWithFruit(p.getFruit());
} else {
doThingWithVegetable(p.getVegetable());
}
}
Esto mejoraría un poco las cosas, pero no sé ... todavía se siente mal.
2. La otra alternativa que pensé fue poner una interfaz en Fruit and Vegetable con las cosas que son comunes para ellos, y usar eso para pasarla. Siento que este es el enfoque más limpio, aunque tendré que usar instanceof
y lanzarlo a Fruit/Vegetable cuando necesite algo que sea específico para ellos.
Entonces, ¿qué más puedo hacer aquí? ¿Y cuáles son las deficiencias de estos enfoques?
ACTUALIZACIÓN: Tenga en cuenta que la pregunta es un poco simplificada, estoy buscando la manera de hacer las cosas CON las "plantas", es decir, el código que en su mayoría "los utiliza" en lugar de hacerles las cosas. Una vez dicho esto, esos métodos similares I Referencia No se puede estar dentro de las "plantas" clases, y usualmente tienen otro argumento, como:
public void createSomethingUsingFruit(Something s, Fruit f);
public void createSomethingUsingVegetable(Something s, Vegetable v);
Es decir, esos métodos tienen otras preocupaciones, además de frutas/hortalizas, y aren' realmente apropiado para cualquier clase de Frutas/Vegetales.
ACTUALIZACIÓN 2: La mayoría del código en esos métodos sólo lee el estado de los objetos de frutas/vegetales, y crear instancias de otras clases de acuerdo con el tipo apropiado, almacenar en la base de datos y así sucesivamente - de mi respuesta a una pregunta en los comentarios que creo que es importante.
¿Qué sucede si la planta no es una fruta o un vegetal? –
Creo que tienes la idea correcta para dirigirte hacia una interfaz genérica. Lea sobre las colecciones también. Tal vez crees una clase de tipo definiendo cualquier método, objeto, variable que necesites para ser flexible como y luego hacer ese concreto en tu main/runtime. –
Si puede implementar funciones comunes para ambos (suponiendo que se basen en los duplicados que mencionó), es mejor usar la clase abstracta ya que puede tener implementación en la clase en sí misma, lo que definitivamente reducirá el código duplicado en la subclase. – Jimmy