Java Tutorial/Design Pattern/Proxy Pattern
Dynamic Proxies
<source lang="java">
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; interface MyClass {
void methodA(String s); void methodB(int i); String methodC(int i, String s);
} public class DynamicProxyDemo {
public static void main(String[] clargs) { MyClass prox = (MyClass) Proxy.newProxyInstance(MyClass.class.getClassLoader(), new Class[] { MyClass.class }, new InvocationHandler() { public Object invoke(Object proxy, Method method, Object[] args) { System.out.println("Method = " + method); if (args != null) { System.out.println("args = "); for (int i = 0; i < args.length; i++) System.out.println("\t" + args[i]); } return null; } }); System.out.println("about to call methodA"); prox.methodA("hello"); System.out.println("finish calling methodA"); prox.methodB(47); prox.methodC(47, "hello"); }
}</source>
Proxy: fronting for another object
<source lang="java">
interface ProxyBase {
void taskOne(); void taskTwo(); void taskThree();
} class Implementation implements ProxyBase {
public void taskOne() { System.out.println("Implementation.f()"); } public void taskTwo() { System.out.println("Implementation.g()"); } public void taskThree() { System.out.println("Implementation.h()"); }
} class Proxy implements ProxyBase {
private ProxyBase implementation; public Proxy() { implementation = new Implementation(); } public void taskOne() { implementation.taskOne(); } public void taskTwo() { implementation.taskTwo(); } public void taskThree() { implementation.taskThree(); }
}
public class ProxyDemo {
public static void main(String args[]) { Proxy p = new Proxy(); p.taskOne(); p.taskTwo(); p.taskThree(); }
}</source>
The PoolManager using Proxy
<source lang="java">
import java.util.ArrayList; class PoolItem {
boolean inUse = false; Object item; PoolItem(Object item) { this.item = item; }
} class ReleasableReference { // Used to build the proxy
private PoolItem reference; private boolean released = false; public ReleasableReference(PoolItem reference) { this.reference = reference; } public Object getReference() { if (released) throw new RuntimeException("Tried to use reference after it was released"); return reference.item; } public void release() { released = true; reference.inUse = false; }
} class PoolManager {
private ArrayList<PoolItem> items = new ArrayList<PoolItem>(); public void add(Object item) { items.add(new PoolItem(item)); } public static class EmptyPoolItem { } public ReleasableReference get() { for (int i = 0; i < items.size(); i++) { PoolItem pitem = (PoolItem) items.get(i); if (pitem.inUse == false) { pitem.inUse = true; return new ReleasableReference(pitem); } } return null; }
} interface Connection {
Object get(); void set(Object x); void release();
} class ConnectionImplementation implements Connection {
public Object get() { return null; } public void set(Object s) { } public void release() { }
} class ConnectionPool { // A singleton
private static PoolManager pool = new PoolManager(); private ConnectionPool() { } public static void addConnections(int number) { for (int i = 0; i < number; i++) pool.add(new ConnectionImplementation()); } public static Connection getConnection() { ReleasableReference rr = (ReleasableReference) pool.get(); if (rr == null) return null; return new ConnectionProxy(rr); }
} class ConnectionProxy implements Connection {
private ReleasableReference implementation; public ConnectionProxy(ReleasableReference rr) { implementation = rr; } public Object get() { return ((Connection) implementation.getReference()).get(); } public void set(Object x) { ((Connection) implementation.getReference()).set(x); } public void release() { implementation.release(); }
} public class ConnectionPoolProxyDemo {
public static void main(String args[]) { try { ConnectionPool.addConnections(5); Connection c = ConnectionPool.getConnection(); c.set(new Object()); c.get(); c.release(); c = ConnectionPool.getConnection(); c.set(new Object()); c.get(); c.release(); c.get(); } catch (Exception e) { System.out.println(e.getMessage()); } }
}</source>