No puede hacer esto directamente en una clase ya que la definición de clase a continuación no se puede compilar debido a la eliminación de tipos genéricos y la declaración de interfaz duplicada.
class TwoTypesConsumer implements Consumer<Apple>, Consumer<Tomato> {
// cannot compile
...
}
Cualquier otra solución para empacar las mismas operaciones de consumo en una clase requiere definir su clase como:
class TwoTypesConsumer { ... }
lo cual no tiene sentido ya que necesita repetir / duplicar la definición de ambas operaciones y no se hará referencia a ellas desde la interfaz. En mi humilde opinión, hacer esto es una pequeña duplicación de código y mal que estoy tratando de evitar.
Esto podría ser un indicador también de que hay demasiada responsabilidad en una clase para consumir 2 objetos diferentes (si no están acoplados).
Sin embargo, lo que estoy haciendo y lo que puede hacer es agregar un objeto de fábrica explícito para crear consumidores conectados de la siguiente manera:
interface ConsumerFactory {
Consumer<Apple> createAppleConsumer();
Consumer<Tomato> createTomatoConsumer();
}
Si en realidad esos tipos están realmente acoplados (relacionados), recomendaría crear una implementación de esta manera:
class TwoTypesConsumerFactory {
// shared objects goes here
private class TomatoConsumer implements Consumer<Tomato> {
public void consume(Tomato tomato) {
// you can access shared objects here
}
}
private class AppleConsumer implements Consumer<Apple> {
public void consume(Apple apple) {
// you can access shared objects here
}
}
// It is really important to return generic Consumer<Apple> here
// instead of AppleConsumer. The classes should be rather private.
public Consumer<Apple> createAppleConsumer() {
return new AppleConsumer();
}
// ...and the same here
public Consumer<Tomato> createTomatoConsumer() {
return new TomatoConsumer();
}
}
La ventaja es que la clase de fábrica conoce ambas implementaciones, hay un estado compartido (si es necesario) y puede devolver más consumidores acoplados si es necesario. No hay declaración de método de consumo repetitivo que no se derive de la interfaz.
Tenga en cuenta que cada consumidor puede ser una clase independiente (aún privada) si no están completamente relacionados.
La desventaja de esa solución es una mayor complejidad de clase (incluso si este puede ser un archivo java) y para acceder al método de consumo necesita una llamada más, en lugar de:
twoTypesConsumer.consume(apple)
twoTypesConsumer.consume(tomato)
tienes:
twoTypesConsumerFactory.createAppleConsumer().consume(apple);
twoTypesConsumerFactory.createTomatoConsumer().consume(tomato);
Para resumir, puede definir 2 consumidores genéricos en una clase de nivel superior utilizando 2 clases internas, pero en caso de llamar, primero debe obtener una referencia al consumidor de implementación apropiado , ya que este no puede ser simplemente un objeto de consumidor.