Call services/methods based on the inputs in Java

Viewed 537

I have a requirement where I need to dynamically call services based on the Input value

Say - if we receive

  1. Input A- Call Service X and Service Y
  2. Input B- Call service Y and Service Z
  3. Input C- call Service Z

Now this list can change, so I am thinking of keepting this list in property file and then loading this at runtime and storing it in a Map

I will have Switch case statement to handle the service invocation like -

  1. If the Input is A then get the service list from the loaded Map
  2. Iterate and call the invokeMethod(Service IDentifier)
  3. invokeMethod will have the switch case
 switch (service name) {
        case "X":
            callServiceX;
            break;
        case "Y":
            callServiceY;
            break;
        case "Z":
            callServiceZ;
            break;
        default:
            break;
    }

Please let me know if there is any other suggestions to improve the above process

2 Answers

I would rather use SpringFramework, but still you can do this with your own, like

interface IService {
    void call(Object param);
}

public static void main(final String[] args) {

    Map<String, IService> services = new TreeMap<>();

    // initialize your services
    services.put("A", new IService(){

            @Override
            public void call(Object param) {

            }
    });

    services.put("B", p -> {});
    services.put("C", System.out::println);

    class D implements IService {
        private Map<String, IService> services;
        public D(Map<String, IService> services) {
            this.services = services;
            services.put("D", this);
        }

        @Override
        public void call(Object p) {
            services.get("A").call("");
            services.get("C").call("");
        }

    }

    D d = new D(services);

    // now check if exists and call them
    if (services.containsKey("D")) {
        services.get("D").call("param");
    }

}

You may have a VowelHandler who knows each of your VowelServices (XServiceImpl, YServiceImpl, ZServiceImpl), and a method that given an input it returns for you the List of services that can handle that.

Your VowelService could be an interface that has the method to check if given some input it returns if the service can handle with that input. This same interface may have a process method just to print which service is running (to mock your desired behavior).

We are almost done here, we can have a subscribe method on VowelHandler interface that allows you to register each of your VowelServices.

interface VowelService {
    boolean canHandle(String vowel);
    void process();
}

class XServiceImpl implements VowelService {
    @Override
    public boolean canHandle(String vowel) {
        return vowel.equals("A");
    }

    @Override
    public void process() {
        System.out.println("Running X service ...");
    }
}

class YServiceImpl implements VowelService {
    @Override
    public boolean canHandle(String vowel) {
        return vowel.equals("A") || vowel.equals("B");
    }

    @Override
    public void process() {
        System.out.println("Running Y service ...");
    }
}

class ZServiceImpl implements VowelService {
    @Override
    public boolean canHandle(String vowel) {
        return vowel.equals("B") || vowel.equals("C");
    }

    @Override
    public void process() {
        System.out.println("Running Z service ...");
    }
}

interface VowelHandler {
    void subscribe(VowelService vowelService);
    List<VowelService> getVowelService(String vowel);
}

class VowelHandlerImpl implements VowelHandler {
    private final List<VowelService> vowelServices = new ArrayList<>();

    @Override
    public void subscribe(VowelService vowelService) {
        vowelServices.add(vowelService);
    }

    @Override
    public List<VowelService> getVowelService(String vowel){
        return vowelServices
                .stream()
                .filter(service -> service.canHandle(vowel))
                .collect(Collectors.toList());
    }
}

And the test:

public static void main(String [] args) {
    VowelHandler vowelHandler = new VowelHandlerImpl();
    VowelService vowelServiceX = new XServiceImpl();
    vowelHandler.subscribe(vowelServiceX);
    VowelService vowelServiceY = new YServiceImpl();
    vowelHandler.subscribe(vowelServiceY);
    VowelService vowelServiceZ = new ZServiceImpl();
    vowelHandler.subscribe(vowelServiceZ);

    List.of("A", "B")
            .forEach(vowel -> vowelHandler
                .getVowelService(vowel)
                    .forEach(VowelService::process)
    );
}

And the output:

Running X service ...
Running Y service ...
Running Y service ...
Running Z service ...

This way we have a loosely coupled code since each class has its own responsibility, then every time you need to create another VowelService, you just need to implement the VowelService interface and subscribe/register to the VowerHandler. This could be done differently if we were focusing on the spring boot approach since you could inject the VowelServices through a List in VowelHandler. So Spring would handle the initialization of each VowelService implementation instead of we registering manually on main method.

Related