zoukankan      html  css  js  c++  java
  • 代理模式

    一.代理模式结构图

    静态代理
    接口:
    public interface PeoPleInterface {
        void vote();
    }
    被代理类:
    public class Farmer implements PeoPleInterface{
        @Override
        public void vote() {
            System.out.println("vote for xiaoming!");
        }
    }
    代理类:
    public class FarmerProxy implements PeoPleInterface{
        private PeoPleInterface peoPle = new Farmer();
        @Override
        public void vote() {
            System.out.println("Before invoke vote" );
            peoPle.vote();
            System.out.println("After invoke vote");
        }
    }
    
    
    调用:
    public static void main(String[] args) {
        HelloProxy helloProxy = new HelloProxy();
        helloProxy.sayHello();
    }
        
    output:
    Before invoke vote
    vote for xiaoming!
    After invoke vote
    静态代理的缺点:由于代理只能为一个类服务,如果需要代理的类很多,那么就需要编写大量的代理类,比较繁琐。

     二.代理模式总结

    定义

    对不适合或者不能直接引用目标对象,代理对象作为客户端和目标对象之间的中介。

    主要优点
    1. 代理对象在客户端与目标对象之间起到一个中介作用和保护目标对象的作用;
    2. 代理对象可以扩展目标对象的功能;
    3. 代理对象能将客户端与目标对象分离,在一定程度上降低了系统的耦合度;

    主要缺点
    多加一个代理对象层,会造成请求处理速度变慢,增加了系统的复杂度;

    模式角色
    抽象主题(Subject)类:通过接口或抽象类声明真实主题和代理对象实现的业务方法。
    真实主题(Real Subject)类:实现了抽象主题中的具体业务,是代理对象所代表的真实对象,是最终要引用的对象。
    代理(Proxy)类:提供了与真实主题相同的接口,其内部含有对真实主题的引用,它可以访问、控制或扩展真实主题的功能。

    应用场景
    远程代理,为了隐藏目标对象存在于不同地址空间的事实,方便客户端访问。例如,本地虚拟的硬盘,用户访问虚拟硬盘时实际访问的是网盘空间。
    安全代理,用于控制不同种类客户对真实对象的访问权限。
    虚拟代理,用于要创建的目标对象开销很大时。例如,下载一幅很大的图像需要很长时间,因某种计算比较复杂而短时间无法完成,这时可以先用小比例的虚拟代理替换真实的对象,消除用户对服务器慢的感觉。
    智能指引,主要用于调用目标对象时,代理附加一些额外的处理功能。例如,增加计算真实对象的引用次数的功能,这样当该对象没有被引用时,就可以自动释放它。
    延迟加载,指为了提高系统的性能,延迟对目标的加载。例如,Hibernate中就存在属性的延迟加载和关联表的延时加载。

    三.代理模式应用实例

     四. 代理模式扩展(动态代理)

    代理模式中,代理类中包含了对真实主题的引用,这样存在两个缺点。
    1. 设计代理以前真实主题必须事先存在,不太灵活。采用动态代理模式可以解决以上问题,如 SpringAOP,其结构图如图 4 所示
    2. 真实主题与代理主题一一对应,增加真实主题也要增加代理。

    动态代理
    利用反射机制在运行时创建代理类。接口、被代理类不变,我们构建一个handler类来实现InvocationHandler接口。
    public class ProxyHandler implements InvocationHandler{//调用处理程序接口
        private Object object;
        public ProxyHandler(Object object){
            this.object = object;
        }
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("Before invoke "  + method.getName());
            method.invoke(object, args);
            System.out.println("After invoke " + method.getName());
            return null;
        }
    }
    
    //通过Proxy类的静态方法newProxyInstance返回一个接口的代理实例。针对不同的代理类,传入相应的代理程序控制器InvocationHandler
    public static void main(String[] args) {
        System.getProperties().setProperty("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
    
        PeoPleInterface farmer = new Farmer();//用接口承接
        InvocationHandler proxyhandler = new ProxyHandler(farmer);//用接口承接
        PeoPleInterface peopleProxy = (PeoPleInterface) Proxy.newProxyInstance(farmer.getClass().getClassLoader(), farmer.getClass().getInterfaces(), proxyhandler);//动态的创建代理对象,用PeoPleInterface接口来承接。
        peopleProxy.vote();
    }
    输出:
    Before invoke vote
    vote for xiaoming!
    After invoke vote

    注意:

    /**
    *获取代理对象
    *loader:被代理对象的classLoader
    *interfaces:被代理对象的接口数组
    *h:代理handler
    */
    Proxy的静态方法:public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h);

  • 相关阅读:
    听说-- 迭代
    听说
    听说---时序图
    闪屏
    WBS
    听说
    Agile Development ----敏捷开发
    软件测试
    需求分析:WBS图
    2048小游戏
  • 原文地址:https://www.cnblogs.com/shijianchuzhenzhi/p/12992786.html
Copyright © 2011-2022 走看看