• 代理模式硬啃


    概念:  为其他对象提供一种代理以控制对这个对象的访问。
    原因: 特定情况下,客户端不能或者不想去直接引用另一个对象,使用代理对象在客户端和目标对象之间作为中介。
    实际应用: 在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就可以回收它了。
      参考:《大话设计模式》
     
     
     
     
     
     
  • 相关阅读:
    Golang 接口(interface)
    Golang 结构体(struct)
    Golang fmt包介绍
    Golang的函数(func)
    Golang数据类型 (map)
    Golang 指针(pointer)
    Golang数据类型 切片(slice)
    操作系统学习笔记(五) 页面置换算法
    Python 元组、列表
    操作系统学习笔记(四) 存储模型和虚拟内存
  • 原文地址:https://www.cnblogs.com/nishilunhui/p/2966095.html
Copyright © 2020-2023  润新知