简体   繁体   中英

What approach to take to make my code more generic Java/ Spring?

In a SpringBoot application I have a service (in the Spring sense) that calls clients that themselves consume RestFul web services by calling a function that is identical to createXXX except that the nature of the object changes at the input of the method. To simplify, let's suppose that I model the creation of animals: with the objects CatDTO , DogDTO , HorseDTO as input of the web services. AnimaslDTO is an object composed of different types of animals (there is no inheritance relationship).

I make the three clients in the same manner let's take the cat's example

package com.animals.client;
import ...

@Service
public class CatClient {

    private static final String CODE_WS_CREATE_CAT = "createCat";
    /**
     * Call RestFul WS for Cat Creation
     * @param catDTO
     */
    public ResponseEntity<String> createCat(CatDTO catDTO)
    {
        // ... Call a RestFul WS in the same manner for each animal. Only the parameter change in each client
        // --> ie dogDTO in DogClient.createDog, HorseDTO in HorseClient.createHorse,
    }
}

In AnimalService implemented by AnimalServiceImpl I try to create the three animals Here is the code

package com.animals.service.impl;

import ...

@Service
public class AnimalServiceImpl implements AnimalService {

    @Autowired
    private CatClient catClient;

    @Autowired
    private DogClient dogClient;

    @Autowired
    private HorseClient horseClient;

    @Override
    public ResponseEntity<String> createAnimals(AnimalsDTO animalsDTO) {
        catClient.createCat(animalsDTO.getCat());
        dogClient.createDog(animalsDTO.getDog());
        horseClient.createHorse(animalsDTO.getHorse());
        .... 
    }
}

I want to know how to generify my clients in Spring or Java for the methods which are very similar to createXXX . What design pattern can I use? What I've tried is to use Java generics but it doesn't fit well with Spring. I've tried to create an AnimalClient(T) class where T is the animal but I have problems in autowiring constructor with one argument.

Thanks by advance!

Unless you have Inheritance , you cannot solve this efficiently even if you try to use Generics

Here is one way to simplify your code:

BaseAnimalDto is a marker interface for now. You can common methods here if you want.

public interface BaseAnimalDTO {

}

CatDTO

public class CatDTO implements BaseAnimalDTO {
    // Cat DTO code
}

Create a BaseAnimalClient as follows

public interface BaseAnimalClient {

    ResponseEntity<String> create(BaseAnimalDTO dto);
}

CatClient looks like this

@Service
public class CatClient implements BaseAnimalClient {

    private static final String CODE_WS_CREATE_CAT = "createCat";

    @Override
    public ResponseEntity<String> create(BaseAnimalDTO dto) {
        return null;
    }
}

Let's create a universal AnimalClient like this:

@Service
public class AnimalClient implements BaseAnimalClient {

    @Autowired
    private CatClient catClient;

    @Autowired
    private DogClient dogClient;

    @Autowired
    private HorseClient horseClient;

    @Override
    public ResponseEntity<String> create(BaseAnimalDTO dto) {
        BaseAnimalClient client;
        if (dto instanceof CatDTO) {
            client = catClient;
        } else if (dto instanceof DogDTO) {
            client = dogClient;
        } else {
            client = horseClient;
        }
        return client.create(dto);
    }
}

Now, your AnimalServiceImpl looks like this

@Service
public class AnimalServiceImpl implements AnimalService {

    @Autowired
    private AnimalClient animalClient;

    @Override
    public ResponseEntity<String> createAnimals(AnimalsDTO animalsDTO) {
        animalClient.create(animalsDTO.getCat());
        animalClient.create(animalsDTO.getDog());
        animalClient.create(animalsDTO.getHorse());
        .... 
    }
}

However, if you can modify your AnimalsDTO like this:

public class AnimalsDTO {

    private List<? extends BaseAnimalDTO> animalDtos;

    // getter, setters

}

Then, your AnimalServiceImpl will be more simplified like this:

@Service
public class AnimalServiceImpl implements AnimalService {

    @Autowired
    private AnimalClient animalClient;

    @Override
    public ResponseEntity<String> createAnimals(AnimalsDTO animalsDTO) {
        for (BaseAnimalDTO animalDTO : animalsDTO.getAnimalDtos()) {
            animalClient.create(animalDTO);
        }
        ....
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM