Processing objects according to the implementation of interfaces in Java

I have been looking for design ideas to solve this problem in Java

I'm using a library (I can't change it). For this example, I just call it "animal" It contains an animal interface and a bunch of implementations; I need to call different methods according to the implementation of animals:

List<Animal> animals = Service.getAnimals();

for(Animal a : animals) {
    process(a);
}

private void process(Animal animal) {

    if (animal instanceOf Cat) {
        processCat(animal);
    } else if (animal instanceOf Dog) {
        processDog(animal);
    } else {
        System.out.println("unsopported animal");
    }
}

I'm currently working on this through reflection. A class contains all "processors" and uses it to call them

String methodName = "process" + Animal getClass().getSimpleName(); //ugh

I'm using java 8 and I'm sure there must be a better design to solve this problem

Any help is appreciated!

Solution

If animal is a sealed class, that is, it is not dynamically extensible and has a limited number of known subclasses, the if instanceof pattern accidentally found in the example is a classic "pattern matching"

If animal is a class you can control, you can use visitor pattern to create an access method directly on animal

However, you declare that animal comes from an external library, which limits the methods you can take

You can still use visitor mode to make all code responsible for interacting with animals in a single class, and use method overloading to resolve types at run time (assuming you don't have any generic problems)

But in fact, it is as inflexible as if instanceof method, which will only make OO people feel better

Therefore, the adopted methods can be summarized as code organization and meaningful methods to the code base

To be honest, if instanceof is what I want unless the number of methods / behaviors starts to become too complex

In this case, I will create a registry to register a processor for each animal type

You can then create a simple class to get the processor required for the animal type from the registry

I've seen this registry mode used a lot in minecraft, but I'm not sure if it has been recorded elsewhere

Basically, its use looks like this

void onApplicationStart(){
    Registry registry = new Registry();
    registry.register(Cat.class,cat -> catProcessor.process(cat));
    registry.register(Dog.class,dog -> dogProcessor.process(dog));
    registry.registerFallback(Animal.class,ani -> animalProcessor.process(ani));
}

Then, you can get the registry and the method of processing

void whenNeeded(Animal animal){
    Registry registry = fetchRegistrySomehow();
    registry.for(animal.getClass()).apply(animal);
}

Edit: deliberately lose the implementation of the registry, because the exact behavior will vary, depending on how you want to find, deal with the class hierarchy, and when and whether the registry should be sealed after some application startup events

The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>