浅谈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();
    }
}

运行结果:

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

原文地址:https://www.cnblogs.com/hmake/p/6101888.html