import java.util.*;
import java.lang.*;
import java.io.*;
import java.lang.reflect.*;
import java.util.concurrent.TimeUnit;

// The main method must be in a class named "Main".
class Main {
    public static void main(String[] args) {
        RealDatabaseService realService = new RealDatabaseService();

        // Create dynamic proxy
        DatabaseService proxyDatabaseService = (DatabaseService) Proxy.newProxyInstance(
                realService.getClass().getClassLoader(),
                new Class[]{DatabaseService.class},
                new DatabaseServiceProxyHandler(realService)
        );

        System.out.println("First Execution:");
        System.out.println(proxyDatabaseService.query("SELECT * FROM users"));
        
        System.out.println("\nSecond Execution:");
        System.out.println(proxyDatabaseService.query("SELECT * FROM users"));
    }
}

// Subject Interface
interface DatabaseService {
    String query(String sql);
}

// Real Subject
class RealDatabaseService implements DatabaseService {
    @Override
    public String query(String sql) {
        System.out.println("Querying database...");

        // Simulate database query delay
        try {
            TimeUnit.SECONDS.sleep(2);
        } catch (InterruptedException ie) {
            Thread.currentThread().interrupt();
        }

        return "Result of query: " + sql;
    }
}

// Proxy Handler
class DatabaseServiceProxyHandler implements InvocationHandler {
    private final RealDatabaseService realService;
    private final Map<Integer, String> cache;

    public DatabaseServiceProxyHandler(RealDatabaseService realService) {
        this.realService = realService;
        this.cache = new HashMap<>();
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        if (!method.getName().equals("query")) return method.invoke(realService, args);

        int hashKey = Arrays.hashCode(new Object[]{method.getName(), Arrays.deepHashCode(args)});
        if (cache.containsKey(hashKey)) {
            System.out.println("Returning result from cache");
            return cache.get(hashKey);
        }

        String result = (String) method.invoke(realService, args);
        cache.put(hashKey, result);
        return result;
    }
}

Embed on website

To embed this project on your website, copy the following code and paste it into your website's HTML: