代理模式:为另一个对象提供一个替身或占位符以控制对这个对象的访问。
代码:
interface Boss { public void meeting(); } class BossImp implements Boss { @Override public void meeting() { System.out.println("meeting ...."); } } class SecretaryProxy implements Boss { private Boss boss; public SecretaryProxy(Boss boss) { this.boss = boss; } @Override public void meeting() { System.out.println("before meeting ...."); boss.meeting(); } } public class ProxyTest { public static void main(String[] args) { Boss boss = new BossImp(); SecretaryProxy proxy = new SecretaryProxy(boss); proxy.meeting(); } }
类图:
这里SecretaryProxy就是一个代理,在Boss开会前会通知Boss开会,还可以控制一些小的会议不用参加。
代理模式和装饰者模式很像,都是用一个对象把被封装对象封装起来,然后调用封装的对象。但是代理模式的目的是控制对象的访问,而装饰者模式是增加对象的行为。这里还有一个小技巧如何控制客户端用的是代理而不是实际的对象,通过提供一个工厂实例化并返回代理。这个实例化的过程可以用工厂模式来实例化。代理模式和适配器模式也很像,都是挡在其他对象前面并负责将请求转发给他们。适配器会改变对象适配的接口,而代理则实现相同的接口。
java本身也提供了一个代理类:
public class ProxyTest { public static void main(String[] args) { User user = new UserImpl(); MyInvocationHandler myInvocationHandler = new MyInvocationHandler(user); User proxy = (User) myInvocationHandler.getProxy(); proxy.add(); User user2 = new UserImpl2(); MyInvocationHandler myInvocationHandler2 = new MyInvocationHandler(user2); User proxy2 = (User) myInvocationHandler2.getProxy(); proxy2.add(); } } interface User { public abstract void add(); public abstract void delete(); } class UserImpl implements User { @Override public void add() { System.out.println("i am in add()"); } @Override public void delete() { System.out.println("i am in delete"); } public void update() { System.out.println("i am in update"); } } class UserImpl2 implements User { @Override public void add() { System.out.println("i am in impl2 add()"); } @Override public void delete() { System.out.println("i am in impl2 delete"); } public void update() { System.out.println("i am in impl2 update"); } } class MyInvocationHandler implements InvocationHandler { private Object target; public MyInvocationHandler(Object target) { this.target = target; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("=================before===================="); Object object = method.invoke(target, args); System.out.println("=================after====================="); return object; } public Object getProxy() { return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), target.getClass().getInterfaces(), this); } }