代理模式(Proxy)

1

定义

  代理模式(Proxy):属于结构型模式,为一个目标对象提供一个代理,通过代理来实现对该目标进行访问,目的是在对象的基础上,增加额外的功能操作。

静态代理

静态代理:目标对象与代理对象一起实现相同的接口或者继承相同的父类。

静态代理有些类似于装饰者模式,装饰者模式将被装饰的对象作为被装饰者的成员变量,静态代理模式将被代理的目标对象作为代理对象的成员变量。

假设有这样一个场景,老师外出培训,通过网络课堂给我们上了一节课。我们直接来看代码即可,非常容易理解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
public interface ITeacher {
void teach();
}

public class Teacher implements ITeacher {
@Override
public void teach() {
System.out.println("老师在上课中");
}
}

public class TeacherProxy implements ITeacher {
private ITeacher target;

public TeacherProxy(ITeacher target) {
this.target = target;
}

@Override
public void teach() {
System.out.println("连接网络视频");
target.teach();
}
}


public class Test {
public static void main(String[] args) {
Teacher teacher = new Teacher();
TeacherProxy proxy = new TeacherProxy(teacher);
proxy.teach();
}
}

动态代理

动态代理:目标对象要实现接口,代理对象不需要实现接口,代理对象的生产利用到JDK的反射机制,会在内存中动态构建代理对象,通过代理对象调用被代理对象的方法,因此也称为JDK代理。

Java中提供了java.lang.reflect.Proxy这样一个类,这个类有一个静态方法Proxy.newProxyInstance(loader, interfaces, h),有三个参数,第一个参数指定目标对象使用的类加载器,第二个参数为目标对象实现的接口类型,第三个参数为事件处理,执行目标对象的方法时,会触发该事件处理,并且把目标对象方法作为参数传入。

第一个参数很好理解,就是目标对象target.getClass().getClassLoader(),第二个参数也很好理解,是目标对象target.getClass().getInterfaces(),第三个参数类似于一个回调,新建一个匿名内部类InvocationHandler,实现invoke()方法,当真正调用目标对象的某个方法时,会将这个方法名和参数传入这个匿名内部类的invoke方法中,在其中添加需要的逻辑即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
public interface ITeacher {
void teach();
}

public class Teacher implements ITeacher {
@Override
public void teach() {
System.out.println("老师在上课中");
}
}

public class TeacherProxyFactory {
private Object target;

public TeacherProxyFactory(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("动态代理开始");
return method.invoke(target, args);
}
});
}
}

public class Test {
public static void main(String[] args) {
ITeacher teacher = new Teacher();
ITeacher proxy = (ITeacher) new TeacherProxyFactory(teacher).getProxyInstance();
proxy.teach();
}
}

类图

1

特点

  小伙伴们看一下代理模式和装饰者模式的类图,只能说一模一样。都是提供一个接口,装饰者模式是装饰对象持有一个接口对象,然后对功能进行扩展。代理模式是代理者持有一个接口对象,对功能进行代理。其本质都是一样的,但是思想上有些差异。

  功能的扩展,一般称为装饰。对象难以获取,接口不对外暴露,一般称为代理。

总结

  在某些情况下,客户不想或者不能直接引用一个委托对象,而代理对象可以在客户和委托对象之间起到中介作用。可以实现代理和委托的分离,降低了系统的耦合性,而且可以防止任意用户都能调用目标对象,起到保护目标对象的作用。

-------------本文结束感谢您的阅读-------------
0%