代理模式
代理模式是一种应用非常广泛的设计模式,当客户端代码需要调用某个对象时,客户端实际上也不关心是否准确得到该对象,它只要一个能提供该功能的对象即可,此时我们就 可返回该对象的代理(Proxy)。
在这种设计方式下,系统会为某个对象提供一个代理对象,并由代理对象控制对源对象的引用。代理就是一个 Java 对象代表另一个 Java 对象来采取行动。在某些情况下,客户端代码不想或不能够直接调用被调用者,代理对象可以在客户和目标对象之间起到中介的作用。
对客户端而言,它不能分辨出代理对象与真实对象的区别,它也无须分辨代理对象和真实对象的区别。客户端代码并不知道真正的被代理对象,客户端代码面向接口编程,它仅仅持有一个被代理对象的接口。
什么情况下可能要使用代理模式?
- 需要创建一个系统开销很大的对象
- 被调用对象在远程主机上
- 目标对象的功能还不足以满足需求
- 。。。。。等等
public interface Image{
void show();
}
//该接口提供了一个实现类,该实现类模拟了一个大图片对象,
//该实现类的构造器使用 Thread.sleep() 方法来暂停 3s。
//下面是该 BigImage 的程序代码。
public class BigImage implements Image{
public BigImage(){
try{
Thread.sleep(3000);
}catch(Exception e){
//省略
}
}
void show(){
System.out.println("打印出很大的一幅图片");
}
}
public class ImageProxy implements Image{
private Image image;
public void show(){
if(image==null) image=new BigImage();
image.show();
}
}
从上面的例子中,我们可以看出,如果用ImageProxy来代理BigImage的话,一开始并不会有3秒延时,只有当必须要调用show()方法的时候,系统才会付出相应的开销,这是非常有用的,很多情况下,对象被创建了之后,我们也许以后根本不会用到,那么系统在创建它时,付出的开销就浪费了,使用了代理之后,我们把这种开销延时到使用的时候,如果这个对象一直不用,那么系统就一直不会付出这部分开销!
Mybatis延时加载
众所周知,查询数据库是一个非常耗时的操作,而有些时候查询到的数据也并没有真正被程序使用。延时加载功能就可以有效避免这种浪费,系统访问数据库时,首先可以得到一个代理对象,此时并没有执行任何数据库查询操作,代理对象中自然也没有真正的数据,当系统真正需要使用数据的时候,再调用代理对象完成数据库查询并返回数据。