Search code examples
javafunctioncall

How can I factorise this code?


I'm working on a java webserver which calls a web service. I'm trying to write some code in a nicer.

I've got 2 similar functions, only one thing changes : the function i have to call depending what i want to do.

public Object updateDef() {
    ExecutorService pool = Executors.newFixedThreadPool(20);
    List<Callable<String>> tasks = new ArrayList<Callable<String>>();

    logger.info("Updating surv def...");

    for (final Surv surv : Client.activatedSurvs) {
        final Client client = new Client(surv.getName(), surv.getPassword());

        tasks.add(new Callable<String>() {
            public String call() throws Exception {
                HERE -> client.updateDef(surv);
                return surv.getId();
            }
        });
        client.destroy();
    }

    List<Future<String>> results = null;
    try {
        results = pool.invokeAll(tasks);
        for (Future<String> future : results) {
            future.get();

        }
    } catch (ExecutionException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    pool.shutdown();

    return null;
}

And the other one :

public Object updateStats() {
    ExecutorService pool = Executors.newFixedThreadPool(20);
    List<Callable<String>> tasks = new ArrayList<Callable<String>>();

    logger.info("Updating surv Stats...");

    for (final Surv surv : Client.activatedSurvs) {
        final Client client = new Client(surv.getName(), surv.getPassword());

        tasks.add(new Callable<String>() {
            public String call() throws Exception {
                HERE -> client.updateStats(surv).toString();
                return surv.getId();
            }
        });
        client.destroy();
    }

    List<Future<String>> results = null;
    try {
        results = pool.invokeAll(tasks);
        for (Future<String> future : results) {
            future.get();
        }
    } catch (ExecutionException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    pool.shutdown();

    return null;
}

So the 2 functions are updateStats and updateDef from class A with a static list from B. The problem is that I've to pass a parameter which is an existing element from this list.

=> A.updateStats(B.list.get(X));

=> A.updateDef(B.list.get(X));

I visited this link How to pass a function as a parameter in Java? but without success

Any idea ?


Solution

  • Your object is to replace:

    tasks.add(new Callable<String>() {
            public String call() throws Exception {
                client.updateStats(surv).toString();
                return surv.getId();
            }
        });
    

    With

    tasks.add(new Callable<String>() {
            public String call() throws Exception {
                doSomething(client, surv);
                return surv.getId();
            }
        });
    

    Which can be done by defining an Interface:

    public interface ClientUpdate {
        public void performUpdate(Client client, Surv surv);
    }
    

    Then, use this interface as a parameter to your method:

    public Object updateStats() {
    

    Becomes

    public Object update(ClientUpdate updater) {
    

    Then use it in your callable

    tasks.add(new Callable<String>() {
            public String call() throws Exception {
                updater.performUpdate(client, surv);
                return surv.getId();
            }
        });
    

    Then implement it:

    updateStats();
    

    becomes:

    update(new ClientUpdate() {
        public void performUpdate(Client client, Surv surv) {
            client.updateStats(surv).toString();
        }
    });
    

    Similarly for updateDef();