Add all 23 GoF design pattern implementations (2026-06-13)

This commit is contained in:
Ankur
2026-06-13 21:44:56 +05:30
commit a5beb61425
106 changed files with 2977 additions and 0 deletions

View File

@@ -0,0 +1,11 @@
package proxy;
/**
* Subject interface — defines what both the real object and proxy expose.
* Clients depend on this, not on the concrete class.
*/
public interface DatabaseConnection {
void connect();
String executeQuery(String sql);
void disconnect();
}

View File

@@ -0,0 +1,52 @@
package proxy;
/**
* Virtual Proxy — delays creating the RealDatabaseConnection until
* the first actual query is made. If no query is ever made (e.g.,
* the service is initialized but never used in this request),
* the expensive connection is never opened.
*
* This is exactly how Hibernate proxies work: entities are not
* loaded from the database until you access a field on them.
*/
public class LazyConnectionProxy implements DatabaseConnection {
private final String url;
private RealDatabaseConnection real; // null until first use
public LazyConnectionProxy(String url) {
this.url = url;
System.out.println("[Proxy] Created for " + url + " (real connection NOT opened yet)");
}
// Lazy initialization — create and connect only on first real need
private void initIfNeeded() {
if (real == null) {
System.out.println("[Proxy] First access — initializing real connection...");
real = new RealDatabaseConnection(url);
real.connect();
}
}
@Override
public void connect() {
// Proxy absorbs the connect() call — real connection opened lazily
System.out.println("[Proxy] connect() called — deferring to first query");
}
@Override
public String executeQuery(String sql) {
initIfNeeded(); // NOW we actually need the connection
return real.executeQuery(sql);
}
@Override
public void disconnect() {
if (real != null) {
real.disconnect();
real = null;
} else {
System.out.println("[Proxy] disconnect() called but connection was never opened");
}
}
}

View File

@@ -0,0 +1,41 @@
package proxy;
import java.time.Instant;
/**
* Logging Proxy — adds timing and audit logging around every query
* without touching RealDatabaseConnection or any of its callers.
*
* This is the "cross-cutting concern" use case of Proxy,
* the same mechanism behind Spring AOP's @Around advice.
*/
public class LoggingProxy implements DatabaseConnection {
private final DatabaseConnection target;
public LoggingProxy(DatabaseConnection target) {
this.target = target;
}
@Override
public void connect() {
System.out.println("[Log] connect() at " + Instant.now());
target.connect();
}
@Override
public String executeQuery(String sql) {
long start = System.currentTimeMillis();
System.out.println("[Log] QUERY START: " + sql);
String result = target.executeQuery(sql);
long elapsed = System.currentTimeMillis() - start;
System.out.println("[Log] QUERY END: " + elapsed + "ms | result: " + result);
return result;
}
@Override
public void disconnect() {
System.out.println("[Log] disconnect() at " + Instant.now());
target.disconnect();
}
}

View File

@@ -0,0 +1,51 @@
package proxy;
/**
* Proxy Design Pattern — Runnable Demo
*
* Shows two proxy types:
* 1. Virtual Proxy (lazy connection)
* 2. Logging Proxy (cross-cutting concern)
* 3. Proxy chaining (both together)
*
* Run: javac proxy/*.java && java proxy.Main
* Article: https://ankurm.com/proxy-design-pattern-java/
*/
public class Main {
public static void main(String[] args) throws InterruptedException {
System.out.println("=== Proxy Design Pattern Demo ===\n");
// --- Virtual Proxy: lazy connection ---
System.out.println("-- Virtual Proxy (lazy loading) --");
DatabaseConnection lazy = new LazyConnectionProxy("jdbc:postgresql://localhost/mydb");
lazy.connect(); // absorbed by proxy, no real connection yet
System.out.println("(no real connection yet — saved startup time)");
System.out.println("Result: " + lazy.executeQuery("SELECT * FROM users WHERE id=1"));
System.out.println("Result: " + lazy.executeQuery("SELECT COUNT(*) FROM orders"));
lazy.disconnect();
System.out.println();
// --- Logging Proxy: wraps the real connection ---
System.out.println("-- Logging Proxy --");
DatabaseConnection real = new RealDatabaseConnection("jdbc:mysql://localhost/shopdb");
real.connect();
DatabaseConnection logged = new LoggingProxy(real);
logged.executeQuery("SELECT * FROM products LIMIT 10");
logged.disconnect();
System.out.println();
// --- Proxy chaining: lazy + logging ---
System.out.println("-- Chained Proxies: Lazy + Logging --");
DatabaseConnection chain =
new LoggingProxy(
new LazyConnectionProxy("jdbc:oracle://localhost/warehouse"));
chain.connect();
chain.executeQuery("SELECT SUM(quantity) FROM inventory");
chain.disconnect();
System.out.println("\n=== Demo complete ===");
}
}

View File

@@ -0,0 +1,33 @@
package proxy;
/**
* Real Subject — the actual, expensive database connection.
* Opening it takes time. We want to delay this until truly needed.
*/
public class RealDatabaseConnection implements DatabaseConnection {
private final String url;
public RealDatabaseConnection(String url) {
this.url = url;
}
@Override
public void connect() {
System.out.println("[Real DB] Connecting to " + url + " (expensive operation)...");
// Simulate connection setup time
try { Thread.sleep(100); } catch (InterruptedException e) { Thread.currentThread().interrupt(); }
System.out.println("[Real DB] Connected.");
}
@Override
public String executeQuery(String sql) {
System.out.println("[Real DB] Executing: " + sql);
return "ResultSet{rows=42}"; // simulated result
}
@Override
public void disconnect() {
System.out.println("[Real DB] Disconnecting from " + url);
}
}