模式名和分类
Proxy
意图
为其他对象提供一种代理以控制对这个对象的访问
动机
1、在实际处理方不方便或者不适合直接出现时,使用代理来响应调用方。远程代理,虚拟代理,
2、主要目的是控制对象的访问,也可以做一定的增强或者和扩展。(spring的aop)
结构
参与者
- 公共接口或者父类 -- Subject
- 实际执行者 -- RealSubject
- 代理执行者 -- Proxy
协作
- 代理类Proxy实现公共接口(或者继承父类),拥有了跟实际执行者一样的方法入口。
- Proxy内部聚合实际执行者 RealSubject
- Proxy在公共方法中,实际使用realSubject来执行方法。
代码实例
https://www.runoob.com/design-pattern/proxy-pattern.html
// 步骤1
// 创建一个接口。Image.java
public interface Image {
void display();
}
// 步骤 2
// 创建实现接口的实体类。RealImage.java
public class RealImage implements Image {
private String fileName;
public RealImage(String fileName){
this.fileName = fileName;
loadFromDisk(fileName);
}
@Override
public void display() {
System.out.println("Displaying " + fileName);
}
private void loadFromDisk(String fileName){
System.out.println("Loading " + fileName);
}
}
// ProxyImage.java
public class ProxyImage implements Image{
private RealImage realImage;
private String fileName;
public ProxyImage(String fileName){
this.fileName = fileName;
}
@Override
public void display() {
if(realImage == null){
realImage = new RealImage(fileName);
}
realImage.display();
}
}
// 步骤 3
// 当被请求时,使用 ProxyImage 来获取 RealImage 类的对象。ProxyPatternDemo.java
public class ProxyPatternDemo {
public static void main(String[] args) {
Image image = new ProxyImage("test_10mb.jpg");
// 图像将从磁盘加载
image.display();
System.out.println("");
// 图像不需要从磁盘加载
image.display();
}
}
//步骤 4
//执行程序,输出结果:
> Loading test_10mb.jpg
> Displaying test_10mb.jpg
> Displaying test_10mb.jpg
已知应用
springAOP动态代理:
- jdk代理:不论是动态还是静态代理,jdk的代理模式,都是通过接口来创建实现类作为代理。jdk只提供接口的代理,而不提供类的代理。
- cglib代理:cglib字节码技术生成的代理,它是通过创建子类来实现代理,正因为如此,所以cglib不能为final和private方法创建代理。
jdk代理在执行性能上远不如cglib动态代理。在高版本的spring中,jdk虽然有优化,但还是不足以跟cglib相提并论。但是!cglib在创建代理对象的过程中,所花费的时间远大于jdk代理。所以:jdk动态代理创建代理对象时比cglib创建对象性能好得多,但是jdk动态代理在执行代理方法时比cglib执行方法时性能差得多。这意味着,如果是单例,因为只需要创建一次代理,使用cglib好得多。如果不是单例,即需要频繁创建代理对象时,使用jdk代理会更好。
相关模式
可以跟适配器模式对比,都是代理执行,但是适配器模式的目的,是为了适配,着重点在于功能的修饰。而代理模式,主要目的是控制对象的访问。