Backend Development 8 min read

Applying Abstract Methods, Anonymous Inner Classes, and Future Pattern for Highly Abstracted Java Service Design

The article demonstrates how to achieve high abstraction in Java by using abstract methods overridden by subclasses, passing behavior through anonymous inner classes, and implementing an asynchronous Future pattern with listeners to handle request results, providing complete code examples for each technique.

Architect's Guide
Architect's Guide
Architect's Guide
Applying Abstract Methods, Anonymous Inner Classes, and Future Pattern for Highly Abstracted Java Service Design

This article explains three techniques for building highly abstracted Java services.

1. Abstract methods for subclass implementation – By defining abstract methods in a base class and letting concrete subclasses provide specific behavior, the common service workflow is centralized while allowing flexible request validation and processing.

public class Test {
    public static void main(String[] args) {
        TestService testService = new TestService();
        testService.getResp(new Object());
    }

    private static class TestService extends BaseService {
        public Object getResp(Object req) {
            return service(req);
        }

        @Override
        protected void validateRequest(Object o) {
            System.out.println("来自TestService的验证");
        }
    }
}

public abstract class BaseService
{
    /**
     * Overall, the service method delegates request validation and business logic to subclasses.
     */
    public final Response service(Request request) {
        System.out.println("调用公共的service");
        validateRequest(request);
        // business logic omitted
        System.out.println("结束调用公共的service");
        return null;
    }

    protected abstract void validateRequest(Request request);
}

2. Passing behavior via anonymous inner classes – When a class has multiple abstract operations, a protected generic method can accept a Command<T> functional interface, allowing callers to supply lambda expressions or anonymous classes for each operation.

public class Provider extends AbstractProvider {
    // Get request
    public void get(final String key) {
        executeCommand(key, () -> System.out.println("执行了获取指令, key:" + key), null);
    }

    // Check existence
    public void exists(final String key) {
        executeCommand(key, () -> System.out.println("执行了判断是否存在指令, key:" + key), null);
    }

    public static void main(String[] args) {
        Provider provider = new Provider();
        provider.get("ss");
        provider.exists("sss");
    }
}

public abstract class AbstractProvider {
    protected
void executeCommand(String key, Command
command, T defaultValue) {
        command.execute();
    }
}

public interface Command
{
    void execute();
}

3. Future pattern for asynchronous execution – The article introduces a RequestFuture that runs a task in a single‑thread executor, allows listeners to be added via compose , and propagates results to ResponseHandleAdapter implementations. It also shows how to chain calls by returning a new future from compose .

public class SendJoinGroupRequest extends AbstractRequestSend implements ResponseHandleAdapter {
    public RequestFuture sendJoinGroupRequest(String s) {
        return send(s).compose(this);
    }

    @Override
    public void onSuccess(String s, RequestFuture future) {
        System.out.println("SendJoinGroupRequest执行结果: " + s);
        future.onComplete(s);
    }

    public static void main(String[] args) {
        SendJoinGroupRequest req = new SendJoinGroupRequest();
        RequestFuture future = req.sendJoinGroupRequest("测试发送JoinGroup检测请求");
        future.addListener(new RequestFutureListener() {
            @Override
            public void onSuccess(String s) {
                System.out.println("我是SendJoinGroupRequest传播出来的,请求为:" + s);
            }
            @Override
            public void onFail() {}
        });
    }
}

public abstract class AbstractRequestSend {
    ExecutorService executorService = Executors.newSingleThreadExecutor();

    public RequestFuture send(String s) {
        RequestFuture requestFuture = new RequestFuture();
        executorService.execute(new AsyncExeRemoteInvoke(requestFuture, s));
        return requestFuture;
    }

    private static class AsyncExeRemoteInvoke implements Runnable {
        private RequestFuture requestFuture;
        private String s;
        public AsyncExeRemoteInvoke(RequestFuture requestFuture, String s) {
            this.requestFuture = requestFuture;
            this.s = s;
        }
        @Override
        public void run() {
            try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); }
            String res = s + "远程调用结束";
            requestFuture.onComplete(res);
        }
    }
}

public class RequestFuture {
    private List
requestFutureListenerList = new ArrayList<>();
    public void onComplete(String s) { fireSuccess(s); }
    private void fireSuccess(String s) { requestFutureListenerList.forEach(l -> l.onSuccess(s)); }
    private void addListener(RequestFutureListener l) { requestFutureListenerList.add(l); }
    public void compose(ResponseHandleAdapter adapter) {
        addListener(new RequestFutureListener() {
            @Override public void onSuccess(String s) { adapter.onSuccess(s, RequestFuture.this); }
            @Override public void onFail() {}
        });
    }
    public void addListener(RequestFutureListener l) { addListener(l); }
}

public interface ResponseHandleAdapter {
    void onSuccess(String s, RequestFuture future);
}

public interface RequestFutureListener {
    void onSuccess(String s);
    void onFail();
}

By combining these patterns, developers can write clean, reusable, and asynchronous service code while keeping the core workflow centralized and extensible.

JavaBackend DevelopmentasynchronousDesign PatternAbstract ClassFuture Pattern
Architect's Guide
Written by

Architect's Guide

Dedicated to sharing programmer-architect skills—Java backend, system, microservice, and distributed architectures—to help you become a senior architect.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.