在静谧的林间舞台上,代理轻舞着对象的梦想,掌控访问,引领旋律,真实与虚幻间,交织出灵动的诗篇。
文章目录
- 一、数据库操作的问题
- 二、代理模式
- 三、代理模式的核心组成
- 四、运用代理模式
- 五、代理模式的应用场景
- 六、小结
- 推荐阅读
一、数据库操作的问题
场景假设:假设我们有一个 Database
类,它有一个 deleteAll
方法可以删除所有数据。如果我们直接让客户端使用这个类,那么任何人都可以调用 deleteAll 方法,这可能会导致重要数据被误删。
public class Database {
public void deleteAll() {
System.out.println("All data deleted");
}
}
public class Client {
public static void main(String[] args) {
Database database = new Database();
database.deleteAll();
}
}
在这个例子中,我们可以看到以下问题:
- 安全性问题:所有人都可以执行任何操作,包括删除数据。这可能会导致数据被误删。
- 性能问题:如果某些操作需要很长时间才能完成,那么用户可能会等待很长时间,这会影响用户体验。
- 维护问题:如果我们想要更改数据库操作的实现,那么我们需要修改所有使用这个类的地方。
二、代理模式
代理模式是一种结构型
设计模式,其目的是为其他对象提供一种代理以控制对这个对象的访问。代理模式在访问对象时引入了一定程度的间接性,可以对访问进行控制和管理,同时也可以在访问对象前后执行额外的操作。
三、代理模式的核心组成
代理模式的核心组成部分主要包括以下三个角色:
- 抽象主题(Subject):这是一个接口,它定义了真实主题和代理对象需要实现的业务方法。
- 真实主题(Real Subject):这是代理对象所代表的真实对象,它实现了抽象主题中的具体业务。
- 代理(Proxy):这个类提供了与真实主题相同的接口,其内部含有对真实主题的引用,它可以访问、控制或扩展真实主题的功能
在这个类图中:
Client
是使用代理的对象。Subject
是定义了 RealSubject 和 Proxy 共有的接口。RealSubject
是真实的对象,Proxy 是它的代理。Proxy
包含一个 RealSubject 对象的引用,它可以访问、控制或扩展 RealSubject 的功能。
四、运用代理模式
场景假设:有一个在线视频服务的场景。在这个场景中,我们有一个 VideoService 类,它有一个 play 方法可以播放视频。然而,我们希望只有付费用户才能播放高清视频,而非付费用户只能播放标清视频。
-
定义抽象主题(Subject):首先,我们需要定义一个接口,这个接口规定了真实主题和代理对象需要实现的方法。
public interface VideoService { void play(String videoId); }
-
实现真实主题(Real Subject):然后,我们需要实现一个真实主题类,这个类实现了抽象主题中的具体业务。
public class RealVideoService implements VideoService { public void play(String videoId) { // 实现播放视频的具体逻辑 System.out.println("Playing video: " + videoId); } }
-
实现代理(Proxy):接下来,我们需要实现一个代理类,这个类也实现了抽象主题的接口,并且内部含有对真实主题的引用,它可以访问、控制或扩展真实主题的功能。
public class VideoServiceProxy implements VideoService { private RealVideoService realVideoService; private boolean isPremiumUser; public VideoServiceProxy(RealVideoService realVideoService, boolean isPremiumUser) { this.realVideoService = realVideoService; this.isPremiumUser = isPremiumUser; } public void play(String videoId) { if (isPremiumUser) { realVideoService.play(videoId); } else { System.out.println("Playing video in standard definition: " + videoId); } } }
-
使用代理:最后,客户端代码可以使用代理对象来代替直接使用真实主题。
public class Client { public static void main(String[] args) { RealVideoService realVideoService = new RealVideoService(); VideoService videoService = new VideoServiceProxy(realVideoService, false); videoService.play("video123"); } }
在这个例子中,VideoServiceProxy 是 RealVideoService 的代理,客户端不直接使用 RealVideoService,而是使用 VideoServiceProxy。这样,我们就可以在 VideoServiceProxy 中添加额外的功能,比如根据用户是否是付费用户来决定播放视频的清晰度,而不需要修改 RealVideoService 的代码。这就是代理模式的优点。
五、代理模式的应用场景
代理模式主要适用于以下几种场景:
-
保护目标对象:代理模式可以用来控制对敏感对象的访问。例如,我们有一个 SensitiveData 类,它有一个 deleteAll 方法可以删除所有敏感数据。我们可以创建一个代理类来控制对 deleteAll 方法的访问,以防止数据被误删。
public interface SensitiveData { void deleteAll(); } public class RealSensitiveData implements SensitiveData { public void deleteAll() { System.out.println("All sensitive data deleted"); } } public class SensitiveDataProxy implements SensitiveData { private RealSensitiveData realSensitiveData; public SensitiveDataProxy(RealSensitiveData realSensitiveData) { this.realSensitiveData = realSensitiveData; } public void deleteAll() { if (checkPermissions()) { realSensitiveData.deleteAll(); } else { System.out.println("Permission denied"); } } private boolean checkPermissions() { // Check user permissions return false; } }
-
增强目标对象:代理模式可以用来增强目标对象的功能。例如,我们有一个 VideoService 类,它有一个 play 方法可以播放视频。我们可以创建一个代理类来增强 play 方法的功能,比如添加日志记录。
public interface VideoService { void play(String videoId); } public class RealVideoService implements VideoService { public void play(String videoId) { System.out.println("Playing video: " + videoId); } } public class VideoServiceProxy implements VideoService { private RealVideoService realVideoService; public VideoServiceProxy(RealVideoService realVideoService) { this.realVideoService = realVideoService; } public void play(String videoId) { logOperation("play", videoId); realVideoService.play(videoId); } private void logOperation(String operation, String videoId) { System.out.println("Log operation: " + operation + " " + videoId); } }
-
网络编程:在网络编程中,代理模式可以用来实现代理服务器。代理服务器可以接收客户端的请求,然后将请求转发给真实的服务器。这样,代理服务器就可以在转发请求之前或之后执行一些额外的操作,比如缓存响应、记录日志等。
public interface Server { void handleRequest(String request); } public class RealServer implements Server { public void handleRequest(String request) { System.out.println("Handling request: " + request); } } public class ProxyServer implements Server { private RealServer realServer; public ProxyServer(RealServer realServer) { this.realServer = realServer; } public void handleRequest(String request) { System.out.println("Received request: " + request); realServer.handleRequest(request); System.out.println("Finished handling request: " + request); } }
六、小结
代理模式是一种强大而灵活的设计模式,通过引入代理对象来控制对真实对象的访问,使得我们可以在访问对象时增加一定的间接性,并且可以在访问前后执行额外的操作。在实际应用中,代理模式被广泛应用于各种场景,帮助我们更好地管理和控制对象的访问。
推荐阅读
- Spring 三级缓存
- 深入了解 MyBatis 插件:定制化你的持久层框架
- Zookeeper 注册中心:单机部署
- 【JavaScript】探索 JavaScript 中的解构赋值
- 深入理解 JavaScript 中的 Promise、async 和 await