Skip to content

代理

更新: 6/22/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 LI SIR LI SIR
The avatar of contributor named as wkwbk wkwbk

页面历史