代理模式
代理模式允许你为其他对象提供一个代理,以控制对这个对象的访问。代理模式在不改变实际对象的情况下,可以在访问对象时添加额外的功能。
可以理解为代理模式为被代理对象创造了一个替身,调用者可以通过这个替身去实现这个被代理对象的功能,这个替身也可以为被代理对象增加功能
静态代理
定义
使用时候需要定义接口或者父类。 代理类和委托类有共同的父类或父接口。
案例
首先定义一个接口 ITeacherDao,并在这个接口中定义一个teacher()方法。
package Static; public interface ITeacherDao { void teacher(); }
再写一个他的实现类,实现teacher()方法
package Static; public class TeacherDao implements ITeacherDao{ @Override public void teacher() { System.out.println("老师在教课"); } }
如上,我们实现了一个简单接口与他的实现类,接下来我们实现一个老师的静态代理类
package Static; public class TeacherDaoProxy implements ITeacherDao{ private TeacherDao teacherDao; public TeacherDaoProxy(TeacherDao teacherDao){ this.teacherDao = teacherDao; } @Override public void teacher() { System.out.println("代理前"); teacherDao.teacher(); System.out.println("代理后"); } }
在这段代码中,我们实现了TeacherDao的代理类,并通过调用teacherDao这个对象使用了被代理对象的方法;我们在使用被代理对象方法前后都拓展了新的功能,这就是静态代理。
下面是主函数对于静态代理的使用
public class Main { public static void main(String[] args) { Static.TeacherDao teacherDao = new TeacherDao(); TeacherDaoProxy teacherDaoProxy = new TeacherDaoProxy(teacherDao); teacherDaoProxy.teacher(); } }
这说明我们的代理类在实现被代理对象的功能时也拓展了新的功能
但是,这样的模式也存在一种缺陷,就是我们的代理对象和被调用对象都要实现同一接口或父类,可能会出现多个代理类,接口如果要增加方法的话会有很多代理类需要维护;针对这一问题,Java的开发者定义了相关方法去解决,这就是我们下面要介绍的被代理类。
动态代理
定义
不需要实现接口,但是被代理的目标对象需要实现,调用jdk的api形成代理对象,
动态代理就是通过使用反射,动态地获取抽象接口的类型,从而获取相关特性进行代理。
案例
我们还是先定义一个接口
public interface ITeacherDao { void teacher(); void sayhello(); }
接着我们定义他的实现类
public class TeacherDao implements ITeacherDao { @Override public void teacher() { System.out.println("老师在教课"); } @Override public void sayhello() { System.out.println("hello"); } }
接着我们实现一个动态的代理类,可以动态代理原对象;在这个代理类中,我们使用到了Proxy.newProxyInstance 这个函数,他有三个参数,以下是三个参数的解释
1.target.getClass().getClassLoader()
:获取被代理对象的类加载器。这是用于加载代理类的类加载器。
2.target.getClass().getInterfaces()
:获取被代理对象实现的接口。这些接口是代理类将要实现的接口。
3.new InvocationHandler() { ... }
:创建一个匿名的 InvocationHandler 对象,它实现了invoke
方法,这是代理逻辑的核心部分。
我们在InvocationHandler() { ... }中调用了被代理对象的方法,并且做了一些扩展
public class FactoryProxy { private Object target; public FactoryProxy(Object target){ this.target = target; } public Object getProxyIstance() { 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("代理前"); Object returnVal = method.invoke(target,args); System.out.println("代理后"); return returnVal; } }); }; }
在主函数中调用被代理类,创建一个接口类,讲接口类传入被代理类,然后就可以定义接口类中的方法了,即实现了动态代理。
public class Main { public static void main(String[] args) { ITeacherDao iteacherDao = new TeacherDao(); ITeacherDao proxyInstance = (ITeacherDao) new FactoryProxy(iteacherDao).getProxyIstance(); proxyInstance.teacher(); proxyInstance.sayhello(); } }
最终输出结果
可以看出,我们通过动态代理类实现了对目标对象的功能拓展