针对问题: 在某些情况下,一个客户不想或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。
代理模式和装饰模式很相似,不同之处在于代理模式是给主题添加控制,但是这些控制来自代理自身的实现,不像装饰模式一样添加的功能来自己主题的子类提供。
装饰模式可以装饰很多次来得到自己想要的实体,类似的代理模式也可以代理很多次,但通常不会这种做,因为这不是代理模式的目的。装饰模式的目的是添加功能,而代理模式的目的是添加控制。
代理模式结构图:
代理模式实现代码:
/** * 抽象主题类 * @author bruce * */ public abstract class Subject { public abstract void request(); } /** * 具体主题类 * @author bruce * */ public class RealSubject extends Subject{ @Override public void request() { // TODO Auto-generated method stub System.out.println("real do something"); } } /** * 代理类 * @author bruce * */ public class Proxy extends Subject{ private Subject subject; public Proxy(Subject subject){ this.subject=subject; } @Override public void request() { // TODO Auto-generated method stub doBefore(); subject.request(); doAfter(); } private void doBefore(){ System.out.println("before doing something"); } private void doAfter(){ System.out.println("after doing something"); } } /** * 测试 * @author bruce * */ public class Client { public static void main(String[] args) { Subject subject=new Proxy(new RealSubject()); subject.request(); /** * output: before doing something real do something after doing something */ } }
动态代理模式:代理模式只能在运行前写好,也就是说是静态的,而动态代理可以在运行时期创建(运用反射)
动态代理模式实现代码:
/** * 抽象主题类 * @author bruce * */ public interface Subject { public void requestA(); public void requestB(); } /** * 具体主题类 * @author bruce * */ public class RealSubject implements Subject{ public void requestA() { // TODO Auto-generated method stub System.out.println("do A"); } public void requestB() { // TODO Auto-generated method stub System.out.println("do B"); } } /** * 代理内容实现 * @author bruce * */ public class SubjectProxy implements InvocationHandler{ private Object object; public SubjectProxy(Object object){ this.subject=subject; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // TODO Auto-generated method stub Object object; if(method.getName().equals("requestA")){ System.out.println("allow to do requestA method"); object=method.invoke(subject, args); return object; }else if(method.getName().equals("requestB")){ System.out.println("not allow to do requestB method"); return null; }else{ System.out.println("other method"); } return null; } } /** * 测试 * @author bruce * */ public class Client { public static void main(String[] args) { RealSubject subject=new RealSubject(); Subject proxy=(Subject)Proxy.newProxyInstance(subject.getClass().getClassLoader(), subject.getClass().getInterfaces(), new SubjectProxy(subject)); System.out.println("------------"); proxy.requestA(); System.out.println("------------"); proxy.requestB(); /** * output: * ------------ allow to do requestA method do A ------------ not allow to do requestB method */ } }