浅谈Java设计模式系列0x0A---代理模式

浅谈Java设计模式系列0x06—适配器模式
浅谈Java设计模式系列0x07—桥接模式
浅谈Java设计模式系列0x08—装饰器模式
浅谈Java设计模式系列0x09—外观模式

上次我给大家介绍了外观模式,它提供了高层的统一接口,使得子系统的使用更加的容易;
本次我给大家介绍的同样也是一种结构型的设计模式—-代理模式;

代理是什么鬼

其实代理比较好理解,就像我们不想到实体店买东西,我们就通过上网,在网上商店购买商品;
我们下单后,网上的代购网站就会帮我们代购商品,购买商品的是代购网站,这个代购网站就是代理了;
代理模式(Proxy Pattern) : 给某一个对象提供一个代理,并由代理对象控制原对象的引用;

模式结构

  • 抽象主题角色(Subject):它声明了真实主题代理主题的共同接口,这样一来在任何使用真实主题的地方都可以使用代理主题,客户端通常需要针对抽象主题角色进行编程;
  • 代理主题角色(Proxy):用来代理和封装真实主题;
  • 真实主题角色(RealSubject):它定义了代理角色所代表的真实对象,在真实主题角色中实现了真实的业务操作,客户端可以通过代理主题角色间接调用真实主题角色中定义的操作;

什么时候能用

根据代理模式的使用目的,常见的代理模式有以下几种类型:

  • 远程(Remote)代理:为一个位于不同的地址空间的对象提供一个本地 的代理对象,这个不同的地址空间可以是在同一台主机中,也可是在 另一台主机中,远程代理又叫做大使(Ambassador);
  • 虚拟(Virtual)代理:如果需要创建一个资源消耗较大的对象,先创建一个消耗相对较小的对象来表示,真实对象只在需要时才会被真正创建;
  • Copy-on-Write代理:它是虚拟代理的一种,把复制(克隆)操作延迟 到只有在客户端真正需要时才执行。一般来说,对象的深克隆是一个 开销较大的操作,Copy-on-Write代理可以让这个操作延迟,只有对象被用到的时候才被克隆;
  • 保护(Protect or Access)代理:控制对一个对象的访问,可以给不同的用户提供不同级别的使用权限;
  • 缓冲(Cache)代理:为某一个目标操作的结果提供临时的存储空间,以便多个客户端可以共享这些结果;
  • 防火墙(Firewall)代理:保护目标不让恶意用户接近;
  • 同步化(Synchronization)代理:使几个用户能够同时使用一个对象而没有冲突;
  • 智能引用(Smart Reference)代理:当一个对象被引用时,提供一些额外的操作,如将此对象被调用的次数记录下来等;

代码示例

本次的代码,我们模仿网络图片的加载来实现代理模式;
代码参考

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
44
45
46
47
48
49
50
51
52
53
54
55
/**
* 抽象角色 声明代理角色和真实角色的共同接口
*/

public interface Photo {
void getPhoto();
}
/**
* 真实角色
*/

public class NetworkPhoto implements Photo {
@Override
public void getPhoto() {
System.out.println("Network Photo is loading");
}
}
/**
* 代理角色:代理对象与真实对象实现相同的接口,所以它能够在任何时刻都能够代理真实对象
* 代理角色内部包含有对真实对象的引用,所以可以操作真实对象,同时也可以附加其他的操作
*/

public class HttpProxy implements Photo {
private NetworkPhoto np;//持有真实对象的引用

public HttpProxy() {
this.np = new NetworkPhoto();
}

/**
*附加操作
*/

private void beforeLoad(){
System.out.println("doing jobs before load.");
}
@Override
public void getPhoto() {
beforeLoad();
np.getPhoto();
afterLoad();
}
/**
*附加操作
*/

private void afterLoad(){
System.out.println("doing jobs after load.");
}
}
/**
* 测试类
*/

public class Client {
public static void main(String []args)
{

HttpProxy proxy=new HttpProxy();
proxy.getPhoto();//通过代理对象引用真实对象
}
}

运行结果

1
2
3
doing jobs before load.
Network Photo is loading
doing jobs after load.

总结

代理模式能够协调调用者和被调用者,在一定程度上降低了系统的耦合度,代理模式对外部提供统一的接口方法,而且代理类在接口中实现对真实类的附加操作行为,从而可以在不影响外部调用情况下,进行系统扩展;
由于在客户端和真实主题之间增加了代理对象,因此有些类型的代理模式可能会造成请求的处理速度变慢,而且有些代理模式的实现非常复杂;

参考

代理模式