Earth Guardian

You are not LATE!You are not EARLY!

0%

设计模式--结构型:代理模式

代理模式:为其他对象提供一种代理以控制对这个对象的访问

代理模式 Proxy

代理模式 Proxy[ˈprɑ:ksi] Pattern:也称为委托模式,控制对象使得只有确实需要这个对象时才创建和初始化。

代理分类

  • 静态代理
    编译前所有的代码已经存在。
  • 动态代理
    通过反射机制动态地生成代理对象,也就是代码编译中并不知道代理关系,动态代理将代理和被代理对象进行了解耦。

常见代理功能

  • 远程代理 Remote Proxy
    常见于 C/S 模式,为某个对象在不同的内存地址空间提供局部代理,使系统可以将 Server 部分实现隐藏,Client 像使用本地对象一样使用 Server
  • 虚拟代理 Virtural Proxy
    使用一个代理对象表示一个十分耗资源的对象,并在真正需要时才创建。
  • 保护代理 Protection Proxy
    使用代理控制对原始对象的访问,这种模式常见于原始对象有不同的访问权限。

具体实例

  • 图片代理
    对大图浏览的控制,用户通过浏览器访问网页时先不加载真实的大图,而是通过代理对象的方法来进行处理,在代理对象的方法中,先使用一个线程向客户端浏览器加载一个小图片,然后在后台使用另一个线程来调用大图片的加载方法将大图片加载到客户端。

静态代理

类图结构

0058-Proxy-uml-classdiag.png

结构解析

  • Subject
    抽象类,申明公共接口。
  • RealSubject
    实现类,被代理类或者被委托类,表示真实对象。
  • 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
34
35
36
37
// 1. Subject
public abstract class Subject {
public abstract void operation();
}

// 2. RealSubject
public class RealSubject extends Subject{
@Override
public void operation() {
System.out.println("RealSubject::operation.");
}
}

// 3. Proxy
public class Proxy extends Subject{
private RealSubject realSubject;

public Proxy() {
this.realSubject = new RealSubject();
}

@Override
public void operation() {
realSubject.operation();
}
}

// 4. Test
public class TestStaticProxy {
public static void main(String[] args) {
Proxy proxy = new Proxy();
proxy.operation();
}
}

// 5. Result
RealSubject::operation.

动态代理

基本接口

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
/*
* 调用被代理对象的方法
* Object: 代理实例
* method:代理实例对应的方法
* args:传入的参数数组
*
/
public interface InvocationHandler {
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable;
}

/*
* 通过 Proxy 的 newProxyInstance 方法来创建代理对象
* ClassLoader: 代理对象的接口,它的 ClassLoader
* Class<?>[]:代理对象的接口,生成的 Class 数组
* InvocationHandler:我们实现的动态代理对象
*/
public class Proxy implements Serializable {
public static Object newProxyInstance(ClassLoader var0,
Class<?>[] var1,
InvocationHandler var2)
throws IllegalArgumentException {...}

}

示例

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
37
38
39
40
41
42
43
// 1. Subject
public interface Subject {
void operation();
}

// 2. RealSubject
public class RealSubject implements Subject{
public void operation(){
System.out.println("RealSubject::operation.");
}
}

// 3. DynamicProxy
public class DynamicProxy implements InvocationHandler{
private Object object;

public DynamicProxy(Object object) {
this.object = object;
}

@Override
public Object invoke(Object o, Method method, Object[] objects)
throws Throwable {
Object result = method.invoke(object, objects);
return result;
}
}

// 4. Test
public class TestDynamicProxy {
public static void main(String[] args) {
RealSubject realSubject = new RealSubject();
InvocationHandler dynamicProxy = new DynamicProxy(realSubject);

Subject subject = (Subject) Proxy.newProxyInstance(
Subject.class.getClassLoader(),
new Class[]{Subject.class}, dynamicProxy);
subject.operation();
}
}

// 5. Result
RealSubject::operation.

总结

在代理模式中,要求给某一个对象提供一个代理,并由代理对象控制对原对象的引用。

  • 优点
    代理模式能够协调调用者和被调用者,降低了系统的耦合度;保护代理可以控制对真实对象的使用权限。
  • 缺点
    于在客户端和真实主题之间增加了代理对象,因此有些类型的代理模式可能会造成请求的处理速度变慢。

参考文档

  • 大话设计模式
  • Android 源码设计模式解析与实战
  • 代理模式