Skip to content

代理

更新: 6/28/2025 字数: 0 字 时长: 0 分钟

定义

代理模式 (Proxy Pattern) 为其他对象提供一种代理以控制对这个对象的访问。代理模式通过引入代理对象间接访问目标对象,实现访问控制、功能增强、延迟加载等目的。

角色

  • 抽象主题 (Subject):定义真实主题和代理的公共接口
  • 真实主题 (Real Subject):实际业务执行对象
  • 代理 (Proxy):控制对真实主题的访问,实现额外功能
  • 客户端 (Client):通过代理访问真实主题

实现

虚拟代理(延迟加载)

java
// 抽象主题
public interface Image {
    void display();
}

// 真实主题
public 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 ignored) {}
    }
    
    @Override
    public void display() {
        System.out.println("显示图片:" + filename);
    }
}

// 代理:控制访问并实现延迟加载
public class ProxyImage implements Image {
    private String filename;
    private RealImage realImage;
    
    public ProxyImage(String filename) {
        this.filename = filename;
    }
    
    @Override
    public void display() {
        if (realImage == null) {
            realImage = new RealImage(filename); // 按需创建
        }
        realImage.display();
    }
}

// 客户端
public class Client {
    public static void main(String[] args) {
        Image image = new ProxyImage("photo.jpg");
        // 此时真实图片未加载
        System.out.println("图片对象已创建");
        
        // 第一次访问触发加载
        image.display();
        System.out.println("---");
        
        // 第二次访问直接显示
        image.display();
    }
}

保护代理(访问控制)

java
// 抽象主题
public interface BankAccount {
    void deposit(double amount);
    void withdraw(double amount);
    double getBalance();
}

// 真实主题
public class RealBankAccount implements BankAccount {
    private double balance;
    
    public RealBankAccount(double initialBalance) {
        this.balance = initialBalance;
    }
    
    @Override
    public void deposit(double amount) {
        balance += amount;
    }
    
    @Override
    public void withdraw(double amount) {
        if (balance >= amount) {
            balance -= amount;
        } else {
            throw new IllegalArgumentException("余额不足");
        }
    }
    
    @Override
    public double getBalance() {
        return balance;
    }
}

// 代理:添加访问控制
public class ProtectedBankAccount implements BankAccount {
    private RealBankAccount realAccount;
    private String owner;
    private String currentUser;
    
    public ProtectedBankAccount(String owner, double initialBalance) {
        this.owner = owner;
        this.realAccount = new RealBankAccount(initialBalance);
    }
    
    public void authenticate(String user) {
        if (user.equals(owner)) {
            currentUser = user;
        } else {
            throw new SecurityException("认证失败");
        }
    }
    
    public void logout() {
        currentUser = null;
    }
    
    private void checkAccess() {
        if (currentUser == null) {
            throw new SecurityException("请先登录");
        }
    }
    
    @Override
    public void deposit(double amount) {
        checkAccess();
        realAccount.deposit(amount);
    }
    
    @Override
    public void withdraw(double amount) {
        checkAccess();
        realAccount.withdraw(amount);
    }
    
    @Override
    public double getBalance() {
        checkAccess();
        return realAccount.getBalance();
    }
}

// 使用示例
public class BankApp {
    public static void main(String[] args) {
        ProtectedBankAccount account = new ProtectedBankAccount("张三", 1000);
        
        // 未认证访问
        try {
            account.getBalance(); // 抛出 SecurityException
        } catch (SecurityException e) {
            System.out.println("错误:" + e.getMessage());
        }
        
        // 认证后访问
        account.authenticate("张三");
        System.out.println("余额:" + account.getBalance());
        account.deposit(500);
        account.withdraw(200);
        System.out.println("新余额:" + account.getBalance());
    }
}

优缺点

优点:

  1. 控制对真实对象的访问
  2. 实现延迟加载,优化性能
  3. 增强目标对象功能(开闭原则)
  4. 降低系统耦合度
  5. 提高系统安全性和扩展性

缺点:

  1. 增加系统复杂度
  2. 可能降低响应速度(多层代理)
  3. 需要额外设计接口
  4. 可能引入额外开销

应用场景

  1. 远程代理(RPC、Web 服务)
  2. 虚拟代理(大资源延迟加载)
  3. 保护代理(访问控制)
  4. 智能引用(对象生命周期管理)
  5. 缓存代理(结果缓存)
  6. 防火墙代理(网络访问控制)

与其他模式的关系

  • 与装饰器模式:都使用包装,但代理控制访问,装饰器增强功能
  • 与适配器模式:适配器改变接口,代理保持接口
  • 与外观模式:外观简化接口,代理控制访问
  • 与桥接模式:桥接分离抽象与实现,代理控制访问

JDK 中的代理模式

  1. Java 动态代理(java.lang.reflect.Proxy
  2. RMI(远程方法调用)
  3. Spring AOP(面向切面编程)
  4. Hibernate 延迟加载(Lazy Initialization)
  5. Java 安全模型(SecurityManager)

注意事项

  1. 区分代理类型(虚拟/保护/远程等)
  2. 避免过度使用导致系统复杂化
  3. 考虑线程安全问题(共享代理状态)
  4. 注意代理链的性能影响
  5. 优先使用标准库代理机制(如 Java 动态代理)
  6. 为远程代理设计健壮的错误处理

贡献者

The avatar of contributor named as AKAcxp AKAcxp

页面历史