【设计模式】结构型-代理模式

在静谧的林间舞台上,代理轻舞着对象的梦想,掌控访问,引领旋律,真实与虚幻间,交织出灵动的诗篇。

一、数据库操作的问题

场景假设:假设我们有一个 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();
    }
}

在这个例子中,我们可以看到以下问题:

  1. 安全性问题:所有人都可以执行任何操作,包括删除数据。这可能会导致数据被误删。
  2. 性能问题:如果某些操作需要很长时间才能完成,那么用户可能会等待很长时间,这会影响用户体验。
  3. 维护问题:如果我们想要更改数据库操作的实现,那么我们需要修改所有使用这个类的地方。

二、代理模式

代理模式是一种结构型设计模式,其目的是为其他对象提供一种代理以控制对这个对象的访问。代理模式在访问对象时引入了一定程度的间接性,可以对访问进行控制和管理,同时也可以在访问对象前后执行额外的操作。

三、代理模式的核心组成

代理模式的核心组成部分主要包括以下三个角色:

  1. 抽象主题(Subject):这是一个接口,它定义了真实主题和代理对象需要实现的业务方法。
  2. 真实主题(Real Subject):这是代理对象所代表的真实对象,它实现了抽象主题中的具体业务。
  3. 代理(Proxy):这个类提供了与真实主题相同的接口,其内部含有对真实主题的引用,它可以访问、控制或扩展真实主题的功能

在这里插入图片描述

在这个类图中:

  1. Client 是使用代理的对象。
  2. Subject 是定义了 RealSubject 和 Proxy 共有的接口。
  3. RealSubject 是真实的对象,Proxy 是它的代理。
  4. Proxy 包含一个 RealSubject 对象的引用,它可以访问、控制或扩展 RealSubject 的功能。

四、运用代理模式

场景假设:有一个在线视频服务的场景。在这个场景中,我们有一个 VideoService 类,它有一个 play 方法可以播放视频。然而,我们希望只有付费用户才能播放高清视频,而非付费用户只能播放标清视频。

  1. 定义抽象主题(Subject):首先,我们需要定义一个接口,这个接口规定了真实主题和代理对象需要实现的方法。

    public interface VideoService {
        void play(String videoId);
    }
    
  2. 实现真实主题(Real Subject):然后,我们需要实现一个真实主题类,这个类实现了抽象主题中的具体业务。

    public class RealVideoService implements VideoService {
        public void play(String videoId) {
            // 实现播放视频的具体逻辑
            System.out.println("Playing video: " + videoId);
        }
    }
    
  3. 实现代理(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);
            }
        }
    }
    
  4. 使用代理:最后,客户端代码可以使用代理对象来代替直接使用真实主题。

    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 的代码。这就是代理模式的优点。

五、代理模式的应用场景

代理模式主要适用于以下几种场景:

  1. 保护目标对象:代理模式可以用来控制对敏感对象的访问。例如,我们有一个 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;
        }
    }
    
  2. 增强目标对象:代理模式可以用来增强目标对象的功能。例如,我们有一个 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);
        }
    }
    
  3. 网络编程:在网络编程中,代理模式可以用来实现代理服务器。代理服务器可以接收客户端的请求,然后将请求转发给真实的服务器。这样,代理服务器就可以在转发请求之前或之后执行一些额外的操作,比如缓存响应、记录日志等。

    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);
        }
    }
    

六、小结

代理模式是一种强大而灵活的设计模式,通过引入代理对象来控制对真实对象的访问,使得我们可以在访问对象时增加一定的间接性,并且可以在访问前后执行额外的操作。在实际应用中,代理模式被广泛应用于各种场景,帮助我们更好地管理和控制对象的访问。

推荐阅读

  1. Spring 三级缓存
  2. 深入了解 MyBatis 插件:定制化你的持久层框架
  3. Zookeeper 注册中心:单机部署
  4. 【JavaScript】探索 JavaScript 中的解构赋值
  5. 深入理解 JavaScript 中的 Promise、async 和 await
  • 27
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值