代理模式
代理模式:为其他对象提供一种代理以控制对这个对象的访问。
这句话看起来有点不明白,个人的理解是代理隐藏了真实的对象,当需要调用真实对象时,通过代理来访问。
结构如图:
代码如下:
package cn.sasa.demo1; public interface ISubject { void request(); }
package cn.sasa.demo1; public class RealSubject implements ISubject{ @Override public void request() { System.out.println("真实的请求"); } }
package cn.sasa.demo1; //代理类 public class Proxy implements ISubject{ RealSubject rsub; @Override public void request() { if(rsub == null) { rsub = new RealSubject(); } rsub.request(); } }
客户端代码:
package cn.sasa.demo1; public class Test { public static void main(String[] args) { Proxy pro = new Proxy(); pro.request(); } }
可以理解为委托人(RealSubject)向代理人(Proxy)做委托,当需要寻找这个委托人的时候,找代理人就可以了。
书中形象的比喻为A代理B向C(目标对象)执行一些操作,代码如下:
package cn.sasa.demo; //委托人和代理人的接口 public interface IAction { void action(); }
package cn.sasa.demo; //委托人 public class Consigner implements IAction{ //委托人知道委托的目标 private Target tar; public Consigner(Target tar) { this.tar = tar; } @Override public void action() { if(tar != null) { System.out.println(tar.name + ",hi~"); } } }
package cn.sasa.demo; //代理人 public class Proxy implements IAction{ //代理人知道委托人 private Consigner conser; //代理人知道要委托的目标 public Proxy(Target tar) { this.conser = new Consigner(tar); } @Override public void action() { conser.action(); } }
package cn.sasa.demo; //目标 public class Target { public String name; }
客户端代码:
package cn.sasa.demo; public class Test { public static void main(String[] args) { //目标对象 Target tar = new Target(); tar.name = "sa"; //代理人 Proxy pro = new Proxy(tar); pro.action(); } }
代理模式的应用场景:
1、远程代理,也就是为一个对象在不同的地址空间提供局部代表。这样可以隐藏一个对象存在于不同地址空间的事实。比如WebService.
2、虚拟代理,根据需要创建开销很大的对象。通过它来存放实例化需要很长时间的真实对象。这样就可以达到性能的最优化。
3、安全代理,用来控制真实对象的访问权限。
4、智能指引,指当调用真实对象时,代理处理另外一些事情。
代理模式其实就是在访问对象时引入一定程度的间接性,因为这种间接性,可以附加多种用途。
以上是静态代理
Java的动态代理是在运行时,动态生成代理对象。
package cn.sasa.Test; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class Test { public static void main(String[] args) { //动态代理:在运行时生成代理类java.lang.reflect.Proxy //loader:被代理的类的加载器 //interfaces:被代理的类实现的接口 //h: ISubject subject = (ISubject) Proxy.newProxyInstance(RealSubject.class.getClassLoader(), new Class[] {ISubject.class}, new InvocationHandler() { //这里的proxy不要用 //method:被代理的对象的方法 //args:被代理的对象的方法的参数 @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //System.out.println("在调用前执行"); if(method.getName().equals("method3")) { if(args != null) { args[0] = ((int)args[0])*2; } } Object obj = method.invoke(new RealSubject(), args); //System.out.println("在调用后执行"); return obj; } }); subject.method1(); System.out.println(subject.method2()); System.out.println(subject.method3(10)); } }
package cn.sasa.Test; public interface ISubject { public void method1(); public String method2(); public int method3(int x); }
package cn.sasa.Test; public class RealSubject implements ISubject{ @Override public void method1() { System.out.println("method1 running......"); } @Override public String method2() { return "hahaha"; } @Override public int method3(int x ){ return x*2; } }