结构型-代理模式

2017-11-18  本文已影响0人  钉某人

源码地址|https://github.com/DingMouRen/DesignPattern

代理模式:在不改变原始类代码的情况下,通过引入代理类来给原始类附加功能。

静态代理类

在不改变原始类(或叫被代理类)的情况下,通过引入代理类来给原始类附加功能。一般情况下,我们让代理类和原始类实现同样的接口。但是,如果原始类并没有定义接口,并且原始类代码并不是我们开发维护的。在这种情况下,我们可以通过让代理类继承原始类的方法来实现代理模式。


/**
 * 抽象接口
 */
public interface Manager {

    void doSomething();
}

/**
 * 被代理类
 */
public class Admin implements Manager{
    @Override
    public void doSomething() {
        System.out.println("Admin--doSomething");
    }
}

/**
 * 代理类
 */
public class AdminProxy1 implements Manager {

    private Admin admin;

    public AdminProxy1(Admin admin) {
        this.admin = admin;
    }

    @Override
    public void doSomething() {
        System.out.println("adminProxy1 -- doSomething");
        admin.doSomething();
    }
}

/**
 * 代理类
 */
public class AdminProxy2 implements Manager {

    private Admin admin;

    public AdminProxy2(Admin admin) {
        this.admin = admin;
    }

    @Override
    public void doSomething() {
        System.out.println("adminProxy2 -- doSomething");
        admin.doSomething();
    }
}

/**
 * 使用类
 */
public class Client {

    public static void main(String[] args) {
        Admin admin = new Admin();

        //代理1执行
        AdminProxy1 adminProxy1 = new AdminProxy1(admin);
        adminProxy1.doSomething();

        //代理2执行
        AdminProxy2 adminProxy2 = new AdminProxy2(admin);
        adminProxy2.doSomething();
    }
}

缺点:静态代理中,需要将被代理类中所有的方法实现一遍,并且为每个方法附加相似的代码逻辑;另外如果要添加的附加功能
的类有多个,需要针对每个类创建一个代理类,增加维护成本。

动态代理

不用事先为每个原始类编写代理类,而是在运行的时候,动态的创建原始类对应的代理类,然后在系统中庸代理类替换原始类。
Java 语言本身就已经提供了动态代理的语法。

/**
 * 抽象接口
 */
public interface Moveable {

    void move();
}

/**
 * 被代理类
 */
public class Car implements Moveable {
    @Override
    public void move() {
        System.out.println("汽车行驶中...");
    }
}

/**
 * 事务处理器
 */
public class TimeHandler implements InvocationHandler {
    private Object target;

    public TimeHandler(Object target) {
        this.target = target;
    }


    /**
     *
     * @param proxy 被代理的对象
     * @param method 被代理对象的方法
     * @param args 方法参数
     * @return  方法返回值
     * @throws Throwable
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        long startTime = System.currentTimeMillis();
        System.out.println("汽车开始行驶");
        method.invoke(target,args);
        long stopTime = System.currentTimeMillis();
        System.out.println("汽车结束行驶");
        System.out.println("汽车行驶时间:"+(stopTime - startTime)+"毫秒");
        return null;
    }
}

/**
 * 使用类
 */
public class Client {
    public static void main(String[] args) {
        Car car = new Car();

        ClassLoader classLoader = car.getClass().getClassLoader();
        Class<?>[] clsArr = car.getClass().getInterfaces();
        InvocationHandler handler = new TimeHandler(car);

        Moveable moveable = (Moveable) Proxy.newProxyInstance(classLoader,
                                                    clsArr,
                                                    handler);
        moveable.move();
    }
}

cglib代理

cglib代理使用需要引入额外的jar包 cglib.jar

/**
 * 被代理类
 */
public class Train {
    public void move(){
        System.out.println("火车行驶中...");
    }
}

/**
 * 代理类
 */
public class CGLibProxy implements MethodInterceptor {
    private Enhancer enhancer = new Enhancer();

    public Object getProxy(Class<?> clazz){
        enhancer.setSuperclass(clazz);
        enhancer.setCallback(this);
        return enhancer.create();
    }

    /**
     * 拦截所有目标类方法的调用
     * @param obj 目标实例对象,被代理类
     * @param method 被代理类的反射对象
     * @param args 方法参数
     * @param methodProxy 代理类的实例
     * @return
     * @throws Throwable
     */
    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        System.out.println("日志开始");
        methodProxy.invokeSuper(obj,args);
        System.out.println("日志结束");
        return null;
    }
}


/**
 * 使用类
 */
public class Client {
    public static void main(String[] args) {
        CGLibProxy proxy = new CGLibProxy();
        Train train = (Train) proxy.getProxy(Train.class);
        train.move();
    }
}

代理模式的应用场景

附:
静态代理需要代理类与被代理类同时实现接口
动态代理类需要被代理类实现接口
cglib不需要代理类或者被代理类实现接口

上一篇 下一篇

猜你喜欢

热点阅读