• 浅谈Java五大设计原则之代理模式


    我们来定义一下  AOP(面向切面编程)

      它是面向对象的一种补充或者是一种增强,它在这基础上增加了一些

    而外的功能增强。

      它可以在原有的行为不改变的前提,在这之前或者之后完成一些而外

    的事情。

    而AOP用的思想和模式就是代理模式。

    代理模式分为两种:

    1.静态代理。

      静态代理的代理类是开发人员自行编写的,并且在编译期就已经

    确定。编写相应的接口和实现类,同时编写一个代理类实现这个接口。

      缺点:

      1.需要为每一个目标对象编写相应得代理实例,从而代理不同的业

    务逻辑。

      2.当接口发生变动时,所有的代理类和实现了都必须修改。

    举个小例子:

    Interface:Computer

    package org.proxy;
    
    /**
     * Created by Administrator on 2016/11/25.
     */
    //编写一个接口
    public interface Computer {
        public void sell( int money );
    }
    

    Class:LenovoComputer

    package org.proxy;
    
    /**
     * Created by Administrator on 2016/11/25.
     */
    //编写一个类,继承Computer接口
    public class LenovoComputer implements Computer {
    
        //重写其方法
        @Override
        public void sell( int money ) {
            System.out.println( "实收金额" + money );
        }
    }
    

    Proxy:LenovoProxy

    package org.proxy;
    
    /**
     * Created by Administrator on 2016/11/25.
     * 编写一个代理对象
     */
    public class LenovoProxy implements Computer {
    
        //定义要代理的对象
        private LenovoComputer lenovo;
    
        //在构造方法中传入LenovoComputer参数
        public LenovoProxy( LenovoComputer lenovo ) {
            this.lenovo = lenovo;
        }
    
        @Override
        public void sell(int money) {
            //在将成本交给厂家之前,先扣去利润
            money = money - 500;
            System.out.println( "代理商赚取了500" );
            //调用方法
            lenovo.sell( money );
        }
    }
    

    Main方法:

    package org.proxy;
    
    /**
     * Created by Administrator on 2016/11/25.
     */
    public class User {
        //main方法
        public static void main(String[] args) {
            //实例化代理对象,代理LenovoComputer,调用其方法
            Computer c = new LenovoProxy( new LenovoComputer() );
            System.out.println( "用户付款了3000元" );
            //调用其方法
            c.sell( 3000 );
        }
    }

    运行结果为:

    2.动态代理。

      使用动态代理,代理实例时不需要开发人员去编写的,而是由相应

    的处理程序在运行时动态产生一个字节码,这个字节码就是代理对象,加

    载到JVM中。由于代理实例时在运行时才会动态产生,因此就叫做动态代理。

    它和静态代理的区别就在于,静态代理的实例时人为编写的,并且编译器就

    已经确定的。

    在Java语言层面实现动态代理的机制有很多,我们只举JDK动态代理。

    JDK动态代理(官方):

    1.Proxy类,用于动态产生代理对象。

    2.InvocationHandler接口,回调处理器,负责调用目标对象的行为,并实现

    功能增强。

      JDK动态代理有一个特点,就是被代理的对象必须要有接口,如果没有接口,是实现不了

    代理的。

    举个例子:

    Work接口:

    package org2.proxy;
    
    /**
     * Created by Administrator on 2016/11/25.
     * 编写一个接口
     */
    public interface Work {
        //接口中的抽象方法
        public void work();
    }

    Teacher类实现Work接口: 

    package org2.proxy;
    
    /**
     * Created by Administrator on 2016/11/25.
     * 编写一个类实现该接口
     */
    public class Teacher implements Work {
    
        //重写方法
        @Override
        public void work() {
            System.out.println( "老师上课了" );
        }
    }
    

    回调处理器:

    package org2.proxy;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    
    /**
     * Created by Administrator on 2016/11/25.
     * 编写一个回调处理器
     * 用于实现功能的增强,和调用目标对象的行为
     */
    public class WorkInvocationHandler implements InvocationHandler {
    
        //这个对象就是被代理的对象
        private Object target;
    
        //将被代理对象传入构造方法中
        public WorkInvocationHandler( Object target ) {
            this.target = target;
        }
    
        //这个方法就是核心的回调方法
        //它可以用来调用被代理对象的具体行为
        //同时在调用目标对象方法之前或者之后做一些事情
        //从而实现功能的增强
        //参数一:代理对象,JDK运行时动态产生
        //参数二:被代理对象需要执行的方法
        //参数三:被代理对象执行的方法所需的参数
        @Override
        public Object invoke(Object proxy, Method method, Object[] args ) throws InvocationTargetException, IllegalAccessException {
            //在调用目标对象行为之前做一些事情
            System.out.println( "before:上课点名" );
    
            //回调目标对象的具体行为
            //回调方法之后一样有返回值,
            //这个返回值就是目标对象的返回值
            Object returnVal = method.invoke( target, args );
    
            //在调用目标对象行为之后做一些事情
            System.out.println( "after:布置作业" );
            return returnVal;
        }
    }
    

    Main方法:

    package org2.proxy;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Proxy;
    
    /**
     * Created by Administrator on 2016/11/25.
     * main方法
     */
    public class Main {
        public static void main(String[] args) {
            //创建需要被代理的对象
            Teacher teacher = new Teacher();
            //创建一个回调处理器,回调处理器会去调用teacher中的方法
            InvocationHandler handler = new WorkInvocationHandler( teacher );
            //使用Proxy类在运行时动态创建一个代理对象
            //上面定义的回调处理器需要传递给这个Proxy类生成代理对象
            //参数一:类加载器
            //参数二:目标对象所实现的所有接口
            //(由于JDK动态代理是基于接口来产生代理对象的,也就是创建出来的代理对象必须要实现一个接口)
            //参数三:回调处理器
            //newProxyInstance方法的返回值就是一个创建好的代理实例
            Work work = ( Work )Proxy.newProxyInstance( Teacher.class.getClassLoader(), teacher.getClass().getInterfaces(), handler );
            //调用其方法
            work.work();
        }
    }
    

    运行结果:

    ---------------------------------------------------------

  • 相关阅读:
    -mysql-锁2
    -mysql-锁机制分为表级锁和行级锁
    JDBC

    JDBC接口介绍之Statement
    JDBC
    -Java-泛型
    JDBC的介绍和数据库的连接
    2014年9月1日 总结
    MediaRecorder test
  • 原文地址:https://www.cnblogs.com/hmake/p/6101888.html
Copyright © 2020-2023  润新知