79

Java 中的三种代理模式

 5 years ago
source link: https://www.ydstudio.net/archives/82.html?amp%3Butm_medium=referral
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

代理模式

代理(Proxy)是一种设计模式,提供了对目标对象另外的访问方式;即通过代理对象访问目标对象.这样做的好处是:可以在目标对象实现的基础上,增强额外的功能操作,即扩展目标对象的功能。

这里使用到编程中的一个思想:不要随意去修改别人已经写好的代码或者方法,如果需改修改,可以通过代理的方式来扩展该方法。

举个例子来说明代理的作用:假设我们想邀请一位明星,那么并不是直接连接明星,而是联系明星的经纪人,来达到同样的目的.明星就是一个目标对象,他只要负责活动中的节目,而其他琐碎的事情就交给他的代理人(经纪人)来解决.这就是代理思想在现实中的一个例子。

代理模式的 关键点是:代理对象与目标对象.代理对象是对目标对象的扩展,并会调用目标对象 .

  1. 静态代理

静态代理在使用时,需要定义接口或者父类,被代理对象与代理对象一起实现相同的接口或者是继承相同父类。

实例说明:

模拟保存动作,定义一个保存动作的接口:IUserDao.java,然后目标对象实现这个接口的方法UserDao.java,此时如果使用静态代理方式,就需要在代理对象(UserDaoProxy.java)中也实现IUserDao接口.调用的时候通过调用代理对象的方法来调用目标对象。

需要 注意 的是,代理对象与目标对象要实现相同的接口,然后通过调用相同的方法来调用目标对象的方法。

接口:IUserDao.java

package net.ydstudio.service;

/**
 * @author Nick
 * @projectName javaLean
 * @package net.ydstudio.service
 * @createDate 2018/08/16 15:35
 * @updateDate 2018/08/16 15:35
 */
public interface IUserDao {

    /**
     * 保存数据库
     * @param: []
     * @return: void
     */
    void save();
}

目标对象:UserDao.java

package net.ydstudio.service.impl;

import net.ydstudio.service.IUserDao;

/**
 * @author Nick
 * @projectName javaLean
 * @package net.ydstudio.service.impl
 * @createDate 2018/08/16 15:36
 * @updateDate 2018/08/16 15:36
 */
public class UserDao implements IUserDao {

    /**
     * 保存数据库
     *
     * @param: []
     * @return: void
     */
    public void save() {
        System.out.println("数据已经保存到数据库");
    }
}

代理对象:UserDaoProxy.java

package net.ydstudio.staticproxy;

import net.ydstudio.service.IUserDao;
import net.ydstudio.service.impl.UserDao;

/**
 * @author Nick
 * @projectName javaLean
 * @package net.ydstudio.staticproxy
 * @createDate 2018/08/16 15:37
 * @updateDate 2018/08/16 15:37
 */
public class UserDaoProxy implements IUserDao {

    /**
     * 保存被代理的对象
     */
    private UserDao target;

    public UserDaoProxy(UserDao target) {
        this.target = target;
    }

    /**
     * 保存数据库
     *
     * @param: []
     * @return: void
     */
    public void save() {
        System.out.println("开始保存数据……");
        target.save();
        System.out.println("结束保存数据……");
    }
}

测试类:

package net.ydstudio.proxy;

import net.ydstudio.service.IUserDao;
import net.ydstudio.service.impl.UserDao;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

import static org.junit.Assert.*;

/**
 * @author Nick
 * @projectName javaLean
 * @package net.ydstudio.proxy
 * @createDate 2018/08/16 15:58
 * @updateDate 2018/08/16 15:58
 */
@RunWith(JUnit4.class)
public class ProxyFactoryTest {

    @Test
    public void test(){
        // 目标对象
        IUserDao target = new UserDao();

        System.out.println(target.getClass());

        // 给目标对象,创建代理对象
        IUserDao proxy = (IUserDao)new ProxyFactory(target).getProxyInstance();
        // class $Proxy()内存中动态生成的代理对象
        System.out.println(proxy.getClass());

        // 执行方法 代理对象
        proxy.save();
    }
}

静态代理总结:

  • 可以在不修改代理目标对象的前提下,对代理目标的功能进行拓展。
  • 需要实现代理目标对象实现的接口,一旦代理目标所实现的接口有修改,目标对象与代理都需要维护。

要解决上面静态代理的缺点,就必须使用动态代理的方式。

动态代理

动态代理有以下特点:

  • 代理对象,不需要实现接口
  • 代理对象的生成,是利用JDK的API,动态的在内存中构建代理对象(需要我们指定创建代理对象/目标对象实现的接口的类型)
  • 动态代理也叫做:JDK代理,接口代理

最后更新于 2018-08-16 16:29:31 并被添加「java」标签,已有 1 位童鞋阅读过。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK