Java代理设计模式

    科技2024-07-12  67

    1.代理设计模式 代理是基本的设计模式之一,它是开发者为了提供额外的或不同的操作,而插入的用来代替“实际”对象的对象。这些操作通常涉及与"实际“对象的通信,因此,代理通常充当着中间人的角色。 说的简单明了一些,你想买包零食,但是自己不想去超市,所以你把钱交给你的女朋友,你的女朋友拿着钱,替你去超市,给你买了零食(当然,后续她会买什么就不知道了)。你的女朋友就充当了这个代理的角色。你可以把下面的SimpleProxy想象为女朋友的角色。

    interface Interface { void doSomething(); void somethingElse(String str); } class RealObject implements Interface{ //被代理对象 @Override public void doSomething() { System.out.println("Do something"); } @Override public void somethingElse(String str) { System.out.println("Something else " + str); } } class SimpleProxy implements Interface{ //代理人 private Interface proxied; //被代理对象 public SimpleProxy(Interface proxied){ this.proxied = proxied; } @Override public void doSomething() { System.out.println("SimpleProxy do something"); proxied.doSomething(); } @Override public void somethingElse(String str) { System.out.println("SimpleProxy something else " + str); proxied.somethingElse(str); } } public class SimpleProxyDemo { public static void consumer(Interface iface){ iface.doSomething(); iface.somethingElse("BOBODA"); } public static void main(String[] args) { consumer(new RealObject()); consumer(new SimpleProxy(new RealObject())); } }

    因为consumer()接收的Interface,所以它无法知道正在获取的到底是RealObject还是SimpleProxy,因为这二者都实现了Interface。但是SimpleProxy已经被插入到了客户端和RealObject之间(你女朋友被你扔到了超市和你家的路上),因此它会执行操作,然后调用RealObject上相同的方法。 在任何时刻,只要你想要将额外的操作,从”实际“对象中分离到不同的地方,特别是当你希望很容易做出修改,并作出额外操作时,代理就很有用。比如,你想统计RealObject中方法所执行的时间,但是你又不想将时间统计代码写入RealObject的方法中,就可以使用代理设计模式,让代理帮你去做,同时也不用更改调用接口。 2.Java中的动态代理。 Java中的动态代理比代理的思想更前进一步,因为它可以动态地创建代理并动态地处理对所代理方法的调用。在动态代理上所做的所有调用都会被重定向到单一的调用处理器上,它的工作是揭示调用的类型,并确定相应的对策。

    import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; class DynamicProxyHandler implements InvocationHandler{ private Object proxied; public DynamicProxyHandler(Object proxied){ this.proxied = proxied; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("**** proxy: " + proxy.getClass() + ", method: " + method +", args : " + args); if (args != null){ for (Object arg : args){ System.out.println(" " + arg); } } return method.invoke(proxied,args); } } public class SimpleDynamicProxy { public static void consumer(Interface iface){ iface.doSomething(); iface.somethingElse("banana"); } public static void main(String[] args) { RealObject realObject = new RealObject(); consumer(realObject); Interface proxy = (Interface) Proxy.newProxyInstance( Interface.class.getClassLoader(), new Class[]{Interface.class}, new DynamicProxyHandler(realObject)); consumer(proxy); } }

    输出

    Do something Something else banana **** proxy: class com.sun.proxy.$Proxy0, method: public abstract void com.thinkInJava.chapter14.Interface.doSomething(), args : null Do something **** proxy: class com.sun.proxy.$Proxy0, method: public abstract void com.thinkInJava.chapter14.Interface.somethingElse(java.lang.String), args : [Ljava.lang.Object;@2503dbd3 banana Something else banana

    通过调用静态方法Proxy.newProxyInstance()可以创建动态代理,这个方法需要三个参数, 第一个是类加载器(通常可以从已经被加载的对象中获取其类加载器,然后传递给它)” 谁要被代理呀?" ,第二个是希望该代理实现的接口列表(不是类或抽象类) " 我是代理,我要实现什么接口才能代理你呀? 参照上面静态代理中,代理人要实现相同接口“ ,第三个是InvocationHandler接口的一个实现 “构造处理代理的实现” 。 动态代理可以将所有调用重定向到调用处理器,因此,通常会向调用处理器的构造函数传递给一个”实际“对象的引用,从而使得调用处理器在执行其中任务时可以将请求转发。

    Processed: 0.011, SQL: 8