Patrón de plantilla con diferentes tipos de entrada en el método invalidado

7

Estoy intentando usar un patrón de plantilla para definir un algoritmo genérico en Java. Pero el método que necesita ser anulado, toma un objeto como entrada. Este objeto variará dependiendo de la implementación concreta.

Así que decidí usar la herencia en el parámetro de entrada. Estoy pasando el objeto principal en el método anulado de la clase abstracta. En el método de anulación de la clase concreta, lo transfiero al niño y obtengo los detalles necesarios. Se dice que el abatimiento es un olor de código. ¿Cómo puedo lograr esto sin derribo? ¿O hay alguna otra solución mejor?

Código de ejemplo que muestra el problema:

abstract class GenericAlgorithm {
    void someMethod(GeneralParameter gp);
}

class ConcreteAlgorithm extends GenericAlgorithm {
    @Override
    void someMethod(GeneralParameter gp) {
        // I can't take a SpecificParameter as argument,
        // so I would need to downcast the parameter
        SpecificParameter sp = (SpecificParameter) gp;
        ...
    }
}
    
pregunta Rishi 21.12.2014 - 11:46

1 respuesta

7

Use genéricos para especificar el tipo de parámetro. La clase padre restringiría este parámetro para que sea una subclase de GeneralParameter :

abstract class GenericAlgorithm<Param extends GeneralParameter> {
    void someMethod(Param p);
}

Luego, la subclase extendería la clase primaria pero proporcionaría el tipo de parámetro utilizado como un argumento de tipo:

class ConcreteAlgorithm extends GenericAlgorithm<SpecificParameter> {
    @Override
    void someMethod(SpecificParameter p) {
        ...
    }
}

Tenga en cuenta que esto puede requerir que también use genéricos para otras partes de su programa si desea evitar el lanzamiento. Aquí hay un ejemplo completo (aunque creado) que crea Sandwiches.

abstract class SandwichMaker<S extends Spread> {
    public void make(S spread) {
        toastBread();
        addSpread(spread);
        enjoy();
    }

    protected void toastBread() {
        System.out.println("...toasting bread");
    }

    protected abstract void addSpread(S spread);

    protected void enjoy() {
        System.out.println("this is yummy!");
    }
}

class CheeseSandwichMaker extends SandwichMaker<Cheese> {
    @Override
    protected void addSpread(Cheese cheese) {
        System.out.println("... adding " + cheese.name + " cheese from " + cheese.origin);
    }
}

interface Spread {}
class Cheese implements Spread {
    public final String name;
    public final String origin;

    public Cheese(String name, String origin) {
        this.name = name;
        this.origin = origin;
    }
}

...

SandwichMaker<Cheese> sandwich = new CheeseSandwichMaker();
sandwich.make(new Cheese("Camembert", "Normandy, France"));
sandwich.make(new Cheese("Cheddar", "Somerset, England"));

Véalo live on ideone .

    
respondido por el amon 21.12.2014 - 12:22

Lea otras preguntas en las etiquetas