代理模式(Proxy Pattern)是一种结构型设计模式,它通过创建一个代理对象来控制对另一个对象的访问。代理对象充当真实对象的替代者,并且可以在访问真实对象之前或者之后执行额外的操作。代理模式常用于延迟加载、权限控制、远程代理、缓存等场景。
代理模式 通过引入代理对象来控制对某个对象的访问。代理对象和真实对象实现相同的接口,客户端对代理对象的操作就像是对真实对象的操作一样,但代理对象可以在操作前或操作后做一些额外的处理。
代理模式通常用于以下几种场景:
代理模式主要涉及以下几个角色:
Subject 接口,定义了代理所代表的真实对象的具体业务逻辑。
Subject 接口,内部持有对真实对象的引用。代理对象可以在调用真实对象方法之前或之后执行一些额外操作。
根据代理的使用场景,代理模式可以分为以下几种类型:
虚拟代理用于延迟加载对象。它会在客户端首次请求真实对象时才创建真实对象实例,并返回给客户端。虚拟代理通常用于大对象、资源消耗大的对象的加载。
远程代理用于对象位于不同地址空间的情况(如跨网络访问)。它代表一个远程对象,通过代理对象来实现对远程对象的访问。常见的应用场景是分布式系统中的远程调用(如 RMI)。
保护代理控制对某个对象的访问权限。它通常会在客户端访问真实对象之前,进行权限验证、日志记录等操作,确保只有合法的操作才会传递到真实对象。
缓存代理用于缓存真实对象的计算结果,避免重复的计算。当请求真实对象时,代理对象先检查缓存,如果存在则直接返回缓存中的结果;如果不存在,则请求真实对象并将结果缓存。
智能代理对真实对象的访问进行了额外的处理,通常用来实现一些辅助功能,如计数、对象生命周期管理等。
+---------------------+
| Subject |<-----------------------+
+---------------------+ |
| + request() | |
+---------------------+ |
^ |
| |
+------------------------+ |
| RealSubject | |
+------------------------+ |
| + request() | |
+------------------------+ |
^ |
| |
+------------------------+ |
| Proxy |-------------------+
+------------------------+
| + request() |
+------------------------+假设我们有一个 RealSubject 类,它表示一个资源管理对象。我们希望控制对该资源的访问,只有合法用户才能访问资源。为此,我们可以使用代理模式,通过一个代理类来控制访问。
// 主题接口(Subject)
interface Subject {
void request();
}
// 真实主题类(RealSubject)
class RealSubject implements Subject {
@Override
public void request() {
System.out.println("RealSubject: Handling request");
}
}
// 代理类(Proxy)
class Proxy implements Subject {
private RealSubject realSubject;
private String userRole;
public Proxy(String userRole) {
this.userRole = userRole;
}
@Override
public void request() {
if (checkAccess()) {
if (realSubject == null) {
realSubject = new RealSubject(); // 延迟加载
}
realSubject.request(); // 代理请求转发给真实主题对象
} else {
System.out.println("Proxy: Access denied.");
}
}
// 检查用户权限
private boolean checkAccess() {
if ("admin".equals(userRole)) {
System.out.println("Proxy: Access granted.");
return true;
} else {
System.out.println("Proxy: Access denied.");
return false;
}
}
}
public class ProxyPatternExample {
public static void main(String[] args) {
// 创建代理对象并检查访问权限
Subject proxy = new Proxy("admin"); // 用户为 admin,访问权限允许
proxy.request();
System.out.println();
Subject proxy2 = new Proxy("user"); // 用户为普通用户,访问权限被拒绝
proxy2.request();
}
}request() 方法,RealSubject 和 Proxy 都实现了该接口。Subject 接口的具体业务逻辑,执行实际的请求处理。RealSubject 的访问,首先检查是否具有访问权限(在本例中是通过 userRole 字段来判断),如果允许访问,则代理请求转发给 RealSubject;否则拒绝访问。Proxy 类中的 checkAccess() 方法根据用户角色来判断是否允许访问。如果角色是 admin,则允许访问;否则拒绝访问。Proxy: Access granted.
RealSubject: Handling request
Proxy: Access denied.在这个例子中,代理模式通过 Proxy 类来控制访问,只有用户角色为 admin 时才能访问 RealSubject。这种方式实现了对真实对象的访问控制和延迟加载。
代理模式可以应用于以下场景:
代理模式通过引入代理对象来控制对真实对象的访问,提供了更灵活的对象访问控制手段。它适用于延迟加载、权限控制、缓存等场景。通过代理,客户端可以与真实对象进行交互,而无需直接与真实对象打交道,从而降低了耦合度和系统的复杂性。在实际应用中,代理模式可以通过增强功能来提高系统的可扩展性和安全性。
如果您有任何问题或建议,欢迎留言讨论。