代理模式(Proxy)总结

目录

  • 代理模式介绍
  • 代理模式的形式
    • 静态代理
      • 基本介绍
      • 代码实现
      • 静态代理优缺点分析:
    • 动态代理
      • 基本介绍
      • 代码实现
      • 总结

代理模式介绍

所谓单例模式,就是为一个对象提供一个替身,以控制对这个对象的访问。即通过代理对象访问目标对象,这样做的好处:可以在目标对象实现的基础上,增强额外的功能操作,即拓展目标对象的功能。

代理模式的形式

主要有三种形式:

  1. 静态代理
  2. 动态代理(JDK代理、接口代理)
  3. Cglib代理(可在内存中动态的创建对象,而不需要实现接口,也属于动态代理的范畴)

静态代理

基本介绍

静态代理在使用时,需要定义接口或者父类,被代理对象(即目标对象)与代理对象一起实现相同的接口或者继承相同的父类。见下图。
代理模式(Proxy)总结_第1张图片

代码实现

接口IntDao.java

public interface IntDao {
    void show();
}

目标对象(被代理对象)ImplDao.java

public class ImplDao implements IntDao{
    @Override
    public void show() {
        System.out.println("目标对象的show方法");
    }
}

代理对象ImplDaoProxy.java

public class ImplDaoProxy implements IntDao {
    private IntDao target;

    public ImplDaoProxy(IntDao target) {
        this.target = target;
    }

    @Override
    public void show() {
        System.out.println("开始代理");
        //完成某些操作
        target.show();
        System.out.println("代理结束");
    }
}

main方法Test.java

public class Test {

    public static void main(String[] args)  {
        //创建被代理对象
        ImplDao implDao = new ImplDao();
        //创建代理对象
        ImplDaoProxy implDaoProxy = new ImplDaoProxy(implDao);
        //通过代理对象,调用被代理对象的方法
        implDaoProxy.show();
    }
}

静态代理优缺点分析:

  1. 优点:不需要修改目标对象,通过代理对象对目标对象功能增强。
  2. 缺点:因为代理对象与被代理对象实现同样的接口,因此需要有很多代理类;
  3. 缺点:一旦接口增加新的方法,代理类与目标类都要进行修改。

代理模式(Proxy)总结_第2张图片

动态代理

基本介绍

  1. 代理对象不需要实现接口,目标对象仍然需要实现接口。
  2. 代理对象通过JDK的API动态的在内存中构建代理对象。
  3. 动态代理也叫做:JDK代理、接口代理。

API:

  1. 所在包java.lang.reflect.Proxy
  2. 核心方法public static Object newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h)

介绍
Proxy.newProxyInstance():产生代理接口的实例。仅能代理实现至少一个接口的类。

ClassLoader:类加载器。即被代理的接口的类加载器。
Class[] interface:被代理对象的父接口
InvocationHandler:将要在代理中实现的功能写在该对象中
InvocationHandler中的invoke方法:调用代理类的任何方法,此方法都会执行

Object proxy:代理对象自身的引用。
Method method:当前被调用的方法。
Object[] args:当前被调用方法用到的参数

代理模式(Proxy)总结_第3张图片

代码实现

接口IntDao.java

public interface IntDao {
    void show();
}

目标对象(被代理对象)ImplDao .javas

public class ImplDao implements IntDao{
    @Override
    public void show() {
        System.out.println("目标对象的show方法");
    }
}

代理对象生成工厂ProxyFactory.java

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class ProxyFactory {
    private Object target;

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

    public Object getProxyInstance() {
        return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(),
                new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        System.out.println("开始代理");
                        //System.out.println(method.getName()); //输出调用的方法名
                        Object returnVal = method.invoke(target, args);
                        System.out.println("代理结束");
                        return returnVal;
                    }
                });
    }

}

测试类Test.java

public class Test {
    public static void main(String[] args) {
        //目标对象
        IntDao target = new ImplDao();
        //创建代理对象
        ProxyFactory proxyFactory = new ProxyFactory(target);
        IntDao proxyInstance = (IntDao)proxyFactory.getProxyInstance();
        //调用目标对象的方法
        proxyInstance.show();
    }
}

总结

动态代理需要实现接口才可以使用。因为使用反射实现,速度不是很快。

你可能感兴趣的:(java,设计模式)