¿Está bien tener "enganches" de instanciación de objetos en las clases base?

StackOverflow https://stackoverflow.com/questions/148056

  •  02-07-2019
  •  | 
  •  

Pregunta

He creado mi propia implementación de árbol para varias razones y he encontrado dos clases, una clase 'base' que es un nodo de árbol genérico repleto de lógica y otra clase que amplía la que está más especializada.

En mi clase base, ciertos métodos implican crear instancias de nuevos nodos de árbol (por ejemplo, agregar hijos). Estas instancias se encuentran dentro de la lógica (en un bucle anidado, por ejemplo) lo que hace que la lógica sea difícil de separar de la instanciación.

Entonces, si no anulo estas instancias en la clase específica, se creará el tipo de nodo incorrecto. Sin embargo, no quiero anular esos métodos porque también contenían lógica compartida que no debería duplicarse.

El problema puede reducirse a esto:

public class Foo {
    public String value() { return "foo"; }

    public Foo doStuff() {
        // Logic logic logic..
        return new Foo();
    }
}

class Bar extends Foo {
    public String value() { return "bar"; } 
}

new Bar().doStuff().value(); // returns 'foo', we want 'bar'

Lo primero que apareció en mi cabeza tendría un 'gancho de creación' que las clases ampliadas podrían anular:

public Foo createFooHook(/* required parameters */) {
  return new Foo();
}

Ahora. Si bien fue un buen primer pensamiento, hay un hedor que sale de ese código algo horrible. Hay algo muy ... mal al respecto.

Es como cocinar desnudo: se siente peligroso e innecesario .

Entonces, ¿cómo lidiarías con esta situación?

¿Fue útil?

Solución

Entonces, después de obtener mi copia de Design Patterns y abrirla para de lo que estoy bastante seguro es de la primera vez que descubrí lo que quiero.

Se llama el Método de fábrica y es sobre todo un ajuste perfecto. Todavía es un poco feo porque mi superclase ( Foo en el ejemplo anterior) no es abstracto, lo que significa que las subclases no están obligadas a implementar el gancho.

Sin embargo, esto puede solucionarse con un poco de refactorización, y terminaré con algo como:

abstract class AbstractFoo {
    public String value() { return "Foo"; }

    public AbstractFoo doStuff() {
        // Logic logic logic
        return hook();
    }

    protected abstract AbstractFoo hook();
}

class Foo extends AbstractFoo {
    protected AbstractFoo hook() { return new Foo(); }
}

class Bar extends AbstractFoo {
    public String value() { return "Bar"; }

    protected AbstractFoo hook() { return new Bar(); }
}

new Bar().doStuff().value(); // Returns 'Bar'!

Otros consejos

Además del patrón de Factory, echaría un vistazo al patrón de Composite: tiende a prestarse bien a trabajar con Factory en situaciones basadas en árboles.

Patrón de diseño compuesto

No creo que haya un mejor enfoque. Solo tenga cuidado de no llamar a estos ganchos desde el constructor.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top