23种设计模式之代理模式
Posted 暴躁的程序猿啊
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了23种设计模式之代理模式相关的知识,希望对你有一定的参考价值。
代理模式(Proxy)
代理模式的基本介绍
1.代理模式:为一个对象提供一个替身,以控制对这个对象的访问,即通过代理对象访问目标对象…这样做的好处是:可以在目标对象实现的基础上,增强额外的功能操作,即扩展目标对象的功能
2.被代理对象可以使远程对象、创建开销大的对象或需要安全控制的对象
3.代理模式有不同的形式,主要有三种静态代理、动态代理(JDK代理、接口代理)、和cglib代理(可以在内存中动态的创建对象,而不需要实现接口,它是属于动态代理的范畴)
静态代理
静态代理在使用时,需要定义接口或者父类,被代理对象(即目标对象)与代理对象一起实现相同的接口或者是继承相同父类
应用实例
1、定义一个接口ITeacherDao
2.目标对象TeacherDao实现ITeacherDao
3.使用静态代理方式,就需要在代理对象TeacherDaoProxy中也实现ITeacherDao
4.调用的时候通过调用代理对象的方法来调用目标对象
5.特别提醒:代理对象与目标对象要实现相同的接口,然后通过调用相同的方法来 调用目标对象方法
接口
/**
* 接口
*/
public interface ITeacherDao {
/**
* 授课的方法
*/
void teach();
}
接口实现
/**
* @create: 2021/10/6
* @author: Tony Stark
*/
public class TeacherDao implements ITeacherDao {
@Override
public void teach() {
System.out.println("老师授课中......");
}
}
代理类实现接口
/**
* 代理类 静态代理
* @create: 2021/10/6
* @author: Tony Stark
*/
public class TeacherDaoProxy implements ITeacherDao {
/**
*目标对象通过接口来聚合
*/
private ITeacherDao target;
/**
* 构造器 构建TeacherDaoProxy对象是传进来一个接口 (实现了接口的具体子类对象)
* @param target
*/
public TeacherDaoProxy(ITeacherDao target) {
this.target = target;
}
@Override
public void teach() {
//加入增强的方法
System.out.println("代理开始 完成一些操作.......");
//执行代理类的方法
target.teach();
//增强的步骤
System.out.println("提交操作 代理结束.......");
}
}
调用
/**
* @create: 2021/10/6
* @author: Tony Stark
*/
public class Client {
public static void main(String[] args) {
//被代理的对象
TeacherDao teacherDao = new TeacherDao();
//代理对象 把背代理对象传给代理对象
TeacherDaoProxy teacherDaoProxy = new TeacherDaoProxy(teacherDao);
//通过代理对象执行方法
teacherDaoProxy.teach();
}
}
输出
代理开始 完成一些操作.......
老师授课中......
提交操作 代理结束.......
静态代理优缺点:
1.优点:在不修改目标对象的功能的前提下,能通过代理对象对目标功能扩展
2.缺点:因为代理对象需要与目标对象实现一样的接口,所以会有很多代理类
3.一旦接口增加方法 就要修改所有
动态代理
1.动态代理,不需要实现接口,但是目标对象要实现接口,否则不能用动态代理
2.代理对象的生成,是利用JDK的API,动态的在内存中构建代理对象
3.动态代理也叫做:JDK代理、接口代理
JDK中生成代理对象API
1.代理类所在包:java.lang.reflect.Proxy
2.JDK实现代理只需要使用newProxyInstance方法,但是该方法需要接收三个参数,完整的写法是
static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)
我们把上面的静态代理改成动态代理
接口
/**
* 接口
*/
public interface ITeacherDao {
/**
* 授课的方法
*/
void teach();
}
实现类
/**
* @create: 2021/10/6
* @author: Tony Stark
*/
public class TeacherDao implements ITeacherDao {
@Override
public void teach() {
System.out.println("老师正在授课...");
}
}
代理
/**
* @create: 2021/10/6
* @author: Tony Stark
*/
public class ProxyFactory {
/**
*维护一个目标对象
*/
private Object target;
/**
* 构造器对target进行初始化
* @param target
*/
public ProxyFactory(Object target) {
this.target = target;
}
/**
* 给目标对象生成一个代理对象
* @return
*/
public Object getProxyInstance(){
//参数说明:
//ClassLoader loader 指定当前目标对象使用的类加载器 获取加载器的方法固定
//Class<?>[] interfaces 目标对象(被代理对象)的接口类型 使用泛型的方式确认类型
//target.getClass().getInterfaces()获取所有接口
//InvocationHandler h 事件处理,执行目标对象方法时
// 会触发事件处理器的方法,会把当前执行的目标对象方法作为参数传入
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("JDK代理开始");
//通过反射调用目标对象的方法
Object invoke = method.invoke(target, args);
return invoke;
}
});
}
}
调用测试
/**
* @create: 2021/10/6
* @author: Tony Stark
*/
public class Client {
public static void main(String[] args) {
//创建目标对象
ITeacherDao target = new TeacherDao();
//给目标对象创建代理对象
ProxyFactory proxyFactory = new ProxyFactory(target);
//返回的是代理对象 一个Object 可以强转成ITeacherDao 不强转调不了方法
ITeacherDao proxyInstance = (ITeacherDao) proxyFactory.getProxyInstance();
//从这里可以看出内存中动态生成了代理对象 class com.sun.proxy.$Proxy0
System.out.println(proxyInstance.getClass());
proxyInstance.teach();
}
}
输出
class com.sun.proxy.$Proxy0
JDK代理开始
老师正在授课...
以上是关于23种设计模式之代理模式的主要内容,如果未能解决你的问题,请参考以下文章