代理模式
代理模式允许你为其他对象提供一个代理,以控制对这个对象的访问。代理模式在不改变实际对象的情况下,可以在访问对象时添加额外的功能。
可以理解为代理模式为被代理对象创造了一个替身,调用者可以通过这个替身去实现这个被代理对象的功能,这个替身也可以为被代理对象增加功能
静态代理
定义
使用时候需要定义接口或者父类。 代理类和委托类有共同的父类或父接口。
案例
首先定义一个接口 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();
}
}
最终输出结果
可以看出,我们通过动态代理类实现了对目标对象的功能拓展
链接
java静态代理与动态代理: java静态代理与动态代理