代理模式(Proxy Pattern),也称为委托模式或 surrogate 模式,是一种结构型设计模式。它为其他对象提供一个代理以控制对这个对象的访问。通过引入代理对象,可以在不改变原始对象接口的前提下,添加额外的功能,如权限检查、延迟加载、日志记录等。代理模式使得客户端可以通过代理间接地操作目标对象,从而实现更灵活和安全的对象交互。
代理模式的特点
- 增强功能:可以在不修改原始对象的情况下为其添加新的行为,例如远程调用、缓存支持、事务管理等。
- 控制访问:可以限制或扩展对目标对象的操作权限,确保只有授权的客户端才能执行特定的方法。
- 延迟初始化:对于资源密集型的对象,可以通过代理模式实现懒加载,即在第一次使用时才创建实际对象。
- 透明性:对于客户端来说,代理和真实主题之间的区别是透明的,它们都实现了相同的接口。
代理模式的分类
根据代理的目的和实现方式,代理模式可以分为以下几种类型:
- 远程代理(Remote Proxy):为一个位于不同地址空间的对象提供局部代表,用于跨越网络边界进行通信。
- 虚拟代理(Virtual Proxy):根据需要创建开销大的对象,通常用于实现延迟加载。
- 保护代理(Protection Proxy):控制对原始对象的访问权限,允许不同的用户有不同的访问级别。
- 智能引用(Smart Reference):除了简单的代理功能外,还可以添加额外的行为,比如计数对象的引用次数、监视对象的访问等。
代理模式的组成
- Subject(抽象主题接口):定义了真实主题和代理类共同的接口,确保两者可以被一致地对待。
- RealSubject(真实主题):实现了
Subject
接口的具体类,负责完成业务逻辑。 - Proxy(代理类):同样实现了
Subject
接口,内部持有一个指向RealSubject
的引用,并在其基础上添加了额外的功能。
代理模式的实现
我们将通过一个简单的例子来演示代理模式的应用:假设我们有一个在线书店系统,其中包含了一个图书库存查询服务。为了提高性能并减少数据库压力,我们可以使用代理模式来实现缓存机制,即当用户请求查看某本书的信息时,先从缓存中查找,如果不存在则去数据库中查询并将结果存入缓存。
示例代码
// 抽象主题接口 - BookService
interface BookService {String findBookInfo(String isbn);
}// 真实主题 - RealBookService
class RealBookService implements BookService {@Overridepublic String findBookInfo(String isbn) {// Simulate database query delaytry {Thread.sleep(1000); // Sleep for a second to simulate DB access time} catch (InterruptedException e) {e.printStackTrace();}return "Book Info from Database: ISBN=" + isbn;}
}// 代理类 - CachedBookService
class CachedBookService implements BookService {private final Map<String, String> cache = new HashMap<>();private final RealBookService realBookService;public CachedBookService() {this.realBookService = new RealBookService();}@Overridepublic String findBookInfo(String isbn) {if (!cache.containsKey(isbn)) {System.out.println("Cache miss, querying database...");String bookInfo = realBookService.findBookInfo(isbn);cache.put(isbn, bookInfo);} else {System.out.println("Cache hit!");}return cache.get(isbn);}
}
使用示例
public class ProxyPatternDemo {public static void main(String[] args) {BookService bookService = new CachedBookService();// 第一次查询会命中数据库System.out.println(bookService.findBookInfo("978-3-16-148410-0"));// 第二次查询会命中缓存System.out.println(bookService.findBookInfo("978-3-16-148410-0"));}
}
代理模式的应用场景
- 当需要在不改变原有对象接口的情况下,为其添加新的功能或行为时。
- 如果想要控制对某些敏感操作的访问权限,可以通过代理模式实现细粒度的安全控制。
- 在处理大型对象或复杂计算时,可以使用虚拟代理来实现延迟加载,优化系统性能。
- 对于分布式的应用程序,远程代理可以帮助隐藏底层的网络通信细节,使客户端能够像调用本地方法一样轻松地调用远程服务。
结语
希望本文能帮助您更好地理解代理模式的概念及其实际应用。如果您有任何疑问或建议,请随时留言交流。