代理模式硬啃

概念:  为其他对象提供一种代理以控制对这个对象的访问。
原因: 特定情况下,客户端不能或者不想去直接引用另一个对象,使用代理对象在客户端和目标对象之间作为中介。
实际应用: 在mini_corba  中,我们使用了proxy,目的是实现调用远程对象。我们把实际是把本地对象注册了一个代理。
 
 
三个角色:
 
1. 抽象主题角色 
2. 代理主题角色 
3. 实际被代理角色 

     ps:图片来自网络
实现代码:
 
 
package com.psyco.proxy;
//抽象角色
public interface   Subject {
           public void doSomething();
 
}
 
 
/*
 * 真实对象
 */
public class RealSubject implements Subject {
 
           public void doSomething() {
                   System. out.println("realStubject done.." );
          }
 
}
 
public class ProxySubject implements Subject {
           private Subject img ;
 
           @Override
           public void doSomething() {
                    if (img == null) {
                              img = new RealSubject();  //这时候才去调用真是对象的方法
                   }
                    img.doSomething();
 
          }
           public void doOtherthing() {
               System.out.print("to do other method");
          }
 
}
 
public class Test {
           public static void main(String[] args) {
                   
                ImgImpl imgl = new ImgImpl();
                imgl.doSomething();
 
                   
          }
          
          
 
}
 
由以上代码可以看出,客户实际需要调用的是RealSubject类的doSomething()方法,现在用ProxySubject来代理 RealSubject类,同样达到目的,同时还可以封装了其他方法(doOtherthing()),可以处理一些其他问题。
 

动态代理类

Java动态代理类位于Java.lang.reflect包下,一般主要涉及到以下两个类:

(1). Interface InvocationHandler:该接口中仅定义了一个方法Object:invoke(Object obj,Method method, Object[] args)。在实际使用时,第一个参数obj一般是指代理类,method是被代理的方法,如上例中的request(),args为该方法的参数数组。 这个抽象方法在代理类中动态实现。


(2).Proxy:该类即为动态代理类,作用类似于上例中的ProxySubject,其中主要包含以下内容:

Protected Proxy(InvocationHandler h):构造函数,估计用于给内部的h赋值。

Static Class getProxyClass (ClassLoader loader, Class[] interfaces):获得一个代理类,其中loader是类装载器,interfaces是真实类所拥有的全部接口的数组。

Static Object newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h):返回代理类的一个实例,返回后的代理类可以当作被代理类使用(可使用被代理类的在Subject接口中声明过的方法)。

 

所谓Dynamic Proxy是这样一种class:它是在运行时生成的class,在生成它时你必须提供一组interface给它,然后该class就宣称它实现了这些 interface。你当然可以把该class的实例当作这些interface中的任何一个来用。当然啦,这个Dynamic Proxy其实就是一个Proxy,它不会替你作实质性的工作,在生成它的实例时你必须提供一个handler,由它接管实际的工作。

 
public class DynamicSubject implements InvocationHandler {
 
           private Subject img ;
 
           public DynamicSubject() {
          }
 
           public DynamicSubject(Subject img) {
                    this.img = img;
          }
 
           @Override
           public Object invoke(Object proxy, Method method , Object[] args)
                              throws Throwable {
                   System. out.println("before calling" + method );
                    method.invoke(img, args);
                   System. out.println("after calling" + method );
                    return null ;
          }
 
}
 
 
public class Test {
           public static void main(String[] args) {
                  
                    // apointe proxy class
                   RealSubject img = new RealSubject();
                   InvocationHandler ds = new DynamicSubject(img);
                    Class cls = img.getClass();
                   
                    //ceate a proxy
                   Subject imgi = (Subject)Proxy. newProxyInstance(cls.getClassLoader(), cls.getInterfaces(),ds);
                   System. out.println(cls.getClassLoader().getClass().getPackage());
                   System. out.println(cls.getInterfaces().getClass().getName());
                   imgi.doSomething();
                   
          }
          
          
 
}
 
 

程序运行结果:
before calling public abstract void Subject.request()
From real subject.
after calling public abstract void Subject.request()

通过这种方式,被代理的对象(RealSubject)可以在运行时动态改变,需要控制的接口(Subject接口)可以在运行时改变,控制的方式(DynamicSubject类)也可以动态改变,从而实现了非常灵活的动态代理关系。

总结:代理模式适合的场合
 
  1. 远程代理,也就是为了一个对象在不同的地址空间提供局部代表,这样可以隐藏一个对象存在于不同地址空间的事实,就像web service里的代理类一样。
  2. 虚拟代理,根据需要创建开销很大的对象,通过它来存放实例化需要很长时间的真实对象,比如浏览器的渲染的时候先显示问题,而图片可以慢慢显示(就是通过虚拟代理代替了真实的图片,此时虚拟代理保存了真实图片的路径和尺寸。
  3. 安全代理,用来控制真实对象访问时的权限,一般用于对象应该有不同的访问权限。
  4. 智能指引,只当调用真实的对象时,代理处理另外一些事情。例如C#里的垃圾回收,使用对象的时候会有引用次数,如果对象没有引用了,GC就可以回收它了。
    参考:《大话设计模式》
 
 
 
 
 
 
原文地址:https://www.cnblogs.com/nishilunhui/p/2966095.html