• 设计模式(第六式:代理模式)


    概念:
      代理模式:为其他对象提供一种代理,以控制对这个对象的访问。
      在代理模式中又分为两种:静态代理和动态代理。代理模式一般默认指静态代理模式。
        静态代理模式:该类型有具体的实现,即就是存在该类型的class文件。
        动态代理模式:及就是只有接口规范,没有具体的实现。也不存在class文件。


    实现:
      静态代理:
        定义代理对象接口:

      public interface Author {
    
                /**
                 * 作家具有写作的能力
                 */
                void write();
            }


        代理对象实现类

            public class NovelAuthor implements Author {

                @Override
                public void write() {
                    System.out.println("我是一个写小说的,现在要准备写小说了");
                }
            }


        代理类实现

            public class ProxyNovelAuthor implements Author {

                private NovelAuthor author;

                public ProxyNovelAuthor() {
                    author = new NovelAuthor();
                }

                @Override
                public void write() {
                    System.out.println("每次写作之前我都要喝杯咖啡,我刚喝完咖啡");
                    author.write();
                    System.out.println("写作完成了,签上我的名字送给你。");
                }
            }


      动态代理:
        代理类接口:

    public interface Author {
    
                /**
                 * 作家具有写作的能力
                 */
                void write();
            }


        代理类Handler,实现InvocationHandler

    public class AuthorInvocationHandler implements InvocationHandler {
    
                private Object obj;
    
                public AuthorInvocationHandler(Object obj) {
                    this.obj = obj;
                }
    
                @Override
                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    
                    System.out.println("我写作之前,都要喝咖啡。");
                    Object result = method.invoke(this.obj, args);
                    System.out.println("我写完了,签名并送给你。");
                    return result;
                }
            }


    测试实现及结果:
      实现:

    @Test
        public void proxyTest() {
    
            ProxyAuthor proxyAuthor = new ProxyAuthor(novelAuthor);
            proxyAuthor.write();
    
        }
    
        @Test
        public void dynamicProxyTest_1() {
    
            AuthorInvocationHandler authorInvocationHandler = new AuthorInvocationHandler((Author) () -> System.out.println("我是现在要准备写小说了"));
    
            ClassLoader classLoader = authorInvocationHandler.getClass().getClassLoader();
            Class[] cls = new Class[]{Author.class};
    
            Author author = (Author) Proxy.newProxyInstance(classLoader, cls, authorInvocationHandler);
            author.write();
        }
    
        @Test
        public void dynamicProxyTest_2() {
    
            AuthorInvocationHandler authorInvocationHandler = new AuthorInvocationHandler((Author) () -> System.out.println("我是现在要准备写一本工具书..."));
    
            ClassLoader classLoader = authorInvocationHandler.getClass().getClassLoader();
            Class[] cls = new Class[]{Author.class};
    
            Author author = (Author) Proxy.newProxyInstance(classLoader, cls, authorInvocationHandler);
            author.write();
        }


      静态代理结果:
        每次写作之前我都要喝杯咖啡,我刚喝完咖啡
        我是一个写小说的,现在要准备写小说了
        写作完成了,签上我的名字送给你。

      动态代理结果1:
        我写作之前,都要喝咖啡。
        我是现在要准备写小说了
        我写完了,签名并送给你。

      动态代理结果2:
        我写作之前,都要喝咖啡。
        我是现在要准备写一本工具书...
        我写完了,签名并送给你。

    分析:
      1.静态代理和动态代理的区别:静态代理必须有代理对象的实现类,动态代理则不需要,有也没关系。静态代理类一般和被代理对象类实现同一个代理对象类接口,目的是为了保证有相同的行为。动态代理对象在使用Proxy静态方法是必须要求传入一个接口类型,所以动态代理接口是必须的。其他的区别都不是核心区别。
      2.都方便扩展,但静态代理没有动态代理方便扩展,但目的都是为了解耦合。
      3.静态代理相当于我们利用重写的方式覆盖了原本的方法,动态代理,是利用反射机制实现的调用方法时,添加一些前后操作。
      4.无论是静态代理还是动态代理,对于代理对象来说,都不能直接访问被代理对象的属性,也就是他们只代理了行为,属性并不会被他们代理。
      5.动态代理在没有具体实现类的情况下,没有属性引用,当然动态代理也可以对代理对象进行具体的实现,这样就能用到里面的属性了。
      6.能在不改变原有对象行为的前提下,对原有行为进行适当的改变。
      7.适用场景:远程代理、智能引用代理、保护代理、缓存代理、同步代理、虚拟代理
        a.RMI远程调用
        b.AOP实现也使用了
        ...

    经典框架中使用的:
      Spring中大量使用,hibernate、mybatis数据库连接池中使用,以及事务控制的也有使用

  • 相关阅读:
    错误网络异常:android.os.NetworkOnMainThreadException
    方法服务android学习笔记42_服务的生命周期
    芯片软件随想录(关于核心技术)
    数组比特【编程珠玑】如何优化程序打印出小于100000的素数
    宋体函数Java乔晓松oracle分组函数
    调试客户端windbg远程调试方法
    方法对象Hibernate联合主键
    文件运行跟踪 root.sh 的 执行过程
    移植交叉编译pcDuino + busybox 成功搭建最小linux系统
    方法定制iOS学习笔记8UITableView的定制
  • 原文地址:https://www.cnblogs.com/ben-mario/p/10709144.html
Copyright © 2020-2023  润新知