软件设计模式-代理模式

  • 代理模式
    • 意图:为其他对象提供一种代理以控制对这个对象的访问。
    • 例子:远程代理(访问远程对象)、虚拟代理(延迟加载大图片)、保护代理(控制权限)。
java 复制代码
// 1. 公共接口
interface Image {
    void display();
}

// 2. 真实对象(远程图片)
class RealImage implements Image {
    private String filename;
    
    public RealImage(String filename) {
        this.filename = filename;
        loadFromDisk(); // 模拟耗时的远程加载
    }
    
    private void loadFromDisk() {
        System.out.println("正在从远程服务器加载图片: " + filename);
        // 模拟网络延迟
        try { Thread.sleep(1000); } 
        catch (InterruptedException e) { e.printStackTrace(); }
    }
    
    @Override
    public void display() {
        System.out.println("显示图片: " + filename);
    }
}

// 3. 虚拟代理(延迟加载代理)
class ImageProxy implements Image {
    private String filename;
    private RealImage realImage;
    
    public ImageProxy(String filename) {
        this.filename = filename;
    }
    
    @Override
    public void display() {
        // 延迟初始化:第一次调用时才创建真实对象
        if (realImage == null) {
            realImage = new RealImage(filename);
        }
        realImage.display();
    }
}

// 4. 保护代理示例
interface SensitiveData {
    void access();
}

class RealData implements SensitiveData {
    private String data;
    
    public RealData(String data) {
        this.data = data;
    }
    
    @Override
    public void access() {
        System.out.println("访问敏感数据: " + data);
    }
}

class ProtectionProxy implements SensitiveData {
    private RealData realData;
    private String userRole;
    
    public ProtectionProxy(String data, String userRole) {
        this.realData = new RealData(data);
        this.userRole = userRole;
    }
    
    @Override
    public void access() {
        // 根据用户角色控制访问权限
        if ("admin".equals(userRole)) {
            realData.access();
        } else {
            System.out.println("拒绝访问:权限不足");
        }
    }
}

// 演示类
public class ProxyPatternDemo {
    public static void main(String[] args) {
        System.out.println("=== 虚拟代理演示(延迟加载)===");
        Image image1 = new ImageProxy("photo1.jpg");
        Image image2 = new ImageProxy("photo2.jpg");
        
        System.out.println("代理对象已创建,但真实图片未加载");
        System.out.println("首次调用display()时才会加载真实图片:");
        image1.display(); // 此时才加载真实图片
        
        System.out.println("\n=== 保护代理演示 ===");
        SensitiveData data1 = new ProtectionProxy("机密数据", "user");
        SensitiveData data2 = new ProtectionProxy("机密数据", "admin");
        
        data1.access(); // 普通用户被拒绝
        data2.access(); // 管理员可访问
        
        System.out.println("\n=== 远程代理演示 ===");
        Image remoteImage = new ImageProxy("remote_image.jpg");
        System.out.println("远程代理已创建");
        remoteImage.display(); // 模拟远程加载过程
    }
}

运行结果:

复制代码

复制代码
=== 虚拟代理演示(延迟加载)===
代理对象已创建,但真实图片未加载
首次调用display()时才会加载真实图片:
正在从远程服务器加载图片: photo1.jpg
显示图片: photo1.jpg

=== 保护代理演示 ===
拒绝访问:权限不足
访问敏感数据: 机密数据

=== 远程代理演示 ===
远程代理已创建
正在从远程服务器加载图片: remote_image.jpg
显示图片: remote_image.jpg

模式要点说明:

  1. 虚拟代理:

    • 延迟创建开销大的对象(如大图片)
    • 第一次访问时才初始化真实对象
    • 优化性能,避免不必要的资源占用
  2. 远程代理:

    • 隐藏远程对象的存在
    • 处理网络通信细节(示例中简化了网络操作)
    • 让客户端像使用本地对象一样使用远程对象
  3. 保护代理:

    • 控制对敏感对象的访问
    • 在代理中添加权限检查逻辑
    • 真实对象无需关心权限验证

代理模式优势:

  • 职责分离:代理对象可以处理附加逻辑(如权限、缓存、日志)
  • 开闭原则:可以在不修改真实对象的情况下增加功能
  • 控制访问:提供更精细的对象访问控制

这个示例展示了代理模式在不同场景下的灵活应用,实际开发中还可以结合动态代理实现更通用的代理逻辑。

相关推荐
YYYing.5 小时前
【设计模式系列 (五) 】原型模式
开发语言·后端·设计模式·原型模式·c/c++
长按助力退休20 小时前
设计模式实战,这 5 个最常用
设计模式
Carl_奕然1 天前
【智能体】Agent的四种设计模式之:Multi-Agent Collaboration
设计模式
Lost of 程序猿1 天前
建造者模式实战:告别“十参数构造函数“的数据导出任务
后端·设计模式·c#·asp.net
SL_staff1 天前
合规性折旧:当知识资产因主权缺位在审计中‘功能性清零’
java·设计模式·开源
Zane19941 天前
工厂方法一定比简单工厂高级?三种工厂模式到底该怎么选
设计模式
Hespethorn1 天前
设计模式是语言缺陷的补丁 —— 从工厂、单例、策略三个模式说起
设计模式
Lost of 程序猿1 天前
命令模式实战:把“下单后的动作“打包成可执行的任务
后端·设计模式·c#·asp.net·命令模式
一只旭宝1 天前
【C++复习】四种类型转换 + 常见设计模式 + Redis/MySQL(后端面试复习完整版)
c++·redis·笔记·mysql·设计模式
YYYing.1 天前
【设计模式系列 (四) 】建造者模式
c++·后端·设计模式·建造者模式·c/c++