代理模式:为其他对象提供额外的访问控制
发布时间: 2023-12-08 14:13:46 阅读量: 27 订阅数: 35
# 1. 理解代理模式
## 1.1 代理模式概述
代理模式是一种结构型设计模式,通过代理对象控制对真实对象的访问,以间接实现在访问对象之前或之后执行额外操作的目的。代理模式可以在不修改目标对象的情况下,扩展目标对象的功能。
## 1.2 代理模式的应用场景
代理模式通常应用于权限控制、远程代理、虚拟代理、缓存代理等场景。例如,数据库连接池中的代理对象可以控制对真实数据库连接的访问,以实现连接复用、统计连接数等功能。
## 1.3 代理模式与其他设计模式的区别与联系
代理模式与装饰器模式在实现上有相似之处,但两者关注点不同:代理模式关注于控制对目标对象的访问,而装饰器模式关注于为对象动态添加功能。此外,代理模式也与单例模式、工厂模式等有一定联系,在实际应用中常结合使用。
以上是代理模式的基本概述,接下来我们将深入探讨代理模式的具体实现方式及其在对象访问控制中的应用。
# 2. 实现代理模式
在第一章中,我们简要介绍了代理模式的概念和应用场景。本章将着重讨论代理模式的实现方式,并探讨代理模式中的委托与调用关系。
### 2.1 静态代理模式的实现方式
静态代理是指在程序运行之前,代理类已经存在的情况下,通过手动编写代理类的方式来实现代理模式。在静态代理中,代理类和目标类需要实现同一接口或继承同一父类。
下面我们通过一个示例来理解静态代理的实现方式。假设我们有一个 `Image` 接口代表图片操作,其中包含一个 `display()` 方法用于显示图片。现在我们需要为该接口实现一个代理类 `ProxyImage`,在显示图片前后添加一些额外的操作。
```java
// Image接口
public interface Image {
void display();
}
// RealImage类,实现Image接口
public class RealImage implements Image {
private String filename;
public RealImage(String filename) {
this.filename = filename;
loadImage();
}
private void loadImage() {
System.out.println("Loading image: " + filename);
}
@Override
public void display() {
System.out.println("Displaying image: " + filename);
}
}
// ProxyImage类,实现Image接口
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);
}
preDisplay();
realImage.display();
postDisplay();
}
private void preDisplay() {
System.out.println("Preparing to display image: " + filename);
}
private void postDisplay() {
System.out.println("Finished displaying image: " + filename);
}
}
// 客户端代码
public class Client {
public static void main(String[] args) {
Image image = new ProxyImage("my_image.jpg");
image.display();
}
}
```
在上述示例代码中,`RealImage` 类代表真正的图片类,实现了 `Image` 接口,并重写了 `display()` 方法。`ProxyImage` 类作为 `RealImage` 类的代理类,同样也实现了 `Image` 接口,并重写了 `display()` 方法,在方法中调用了 `RealImage` 类的 `display()` 方法。在 `display()` 方法的前后,我们添加了一些额外的操作,例如显示前的准备和显示后的结束语句。
通过运行客户端代码,我们可以观察到代理类在调用真正的图片类之前和之后执行了额外的操作。
### 2.2 动态代理模式的实现方式
与静态代理不同的是,动态代理是在程序运行时动态生成代理类的方式。动态代理可通过 Java 提供的 `java.lang.reflect.Proxy` 类和 `java.lang.reflect.InvocationHandler` 接口来实现。
下面我们通过一个示例来了解动态代理的实现方式。假设我们有一个 `Calculator` 接口代表计算器,其中包含 `add()` 方法用于进行加法运算。现在我们需要为该接口实现一个代理类 `CalculatorProxy`,在进行加法运算前后记录日志。
```java
// Calculator接口
public interface Calculator {
int add(int a, int b);
}
// CalculatorImpl类,实现Calculator接口
public class CalculatorImpl implements Calculator {
@Override
public int add(int a, int b) {
return a + b;
}
}
// CalculatorInvocationHandler类,实现InvocationHandler接口
public class CalculatorInvocationHandler implements InvocationHandler {
private Object target;
public CalculatorInvocationHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
preInvoke(method);
Object result = method.invoke(target, args);
```
0
0