[5] [接口隔离] ( 2 ) 代理模式 proxy

总结

  • 什么情况下用代理模式?
    出于某种原因(创建对象开销/安全控制/跨进程访问...),
    直接访问会造成很多麻烦,
    这时需要增加间接层,使用代理模式.


  • GOF定义
    为其他对象提供一种代理以控制(隔离, 使用接口)对这个对象的访问.
    (重点是控制该对象的访问)


  • 具体做法?
    创建一个类, 让这个类充当其他事物的接口.


  • 实际场景情况?
    proxy并不一定要求保持接口完整的一致性,
    只要能够实现简介控制,
    有时候损失一些透明性是可以接受的.


  • 代理类型?
    虚拟代理
    缓存代理
    保护代理
    远程代理
    智能应用代理


  • 应用场景?
    缓存
    访问控制
    延迟实例化
    远程访问
    额外的行为




image




java例子1

缓存代理/虚拟代理

.
这个例子中,
使用代理模式,
可以起到缓存效果,
优化计算资源.

package v21_proxy.java;

// 图片爬虫类
class  RemoteImage {
    private String url; // 图片url来源

    public RemoteImage(String url) {
        this.url = url;
    }

    // 负责加载展示图片
    public void displayImage() {
        // 模拟加载和展示...
        System.out.println("Displaying image from URL: " + url);
        // Code to load and display the image
    }
}

// 代理类
public class ImageProxy {
    private String url;
    private RemoteImage image; // 图片爬虫对象

    public ImageProxy(String url) {
        this.url = url;
        this.image = null;
    }

    public void displayImage() {
        // 起到缓存效果.
        if (image == null) {
            System.out.println("New image from URL: " + url);
            image = new RemoteImage(url);
        }
        image.displayImage();
    }

    public static void main(String[] args) {
        ImageProxy imageProxy = new ImageProxy("http://example.com/image.jpg");
        imageProxy.displayImage(); // Image is loaded from the server
        imageProxy.displayImage(); // Image is loaded from the cache
    }
}





java例子2

保护代理

package v21_proxy.java;

// 银行账户
interface BankAccount {
    void deposit(double amount);  // 存款
    void withdraw(double amount); // 提款
}

// 真实账户对象
class RealBankAccount implements BankAccount {
    private double balance;

    public RealBankAccount(double initialBalance) {
        this.balance = initialBalance;
    }

    @Override
    public void deposit(double amount) {
        balance += amount;
        System.out.println("Deposited: " + amount + ", new balance: " + balance);
    }

    @Override
    public void withdraw(double amount) {
        if (balance >= amount) {
            balance -= amount;
            System.out.println("Withdrew: " + amount + ", new balance: " + balance);
        } else {
            System.out.println("Insufficient balance");
        }
    }
}

// 代理账户对象
class BankAccountProxy implements BankAccount {
    private RealBankAccount realBankAccount;
    private String userRole;

    public BankAccountProxy(String userRole, double initialBalance) {
        this.userRole = userRole;
        this.realBankAccount = new RealBankAccount(initialBalance);
    }

    @Override
    public void deposit(double amount) {
        // 存款没有限制
        if (userRole.equals("Admin") || userRole.equals("User")) {
            realBankAccount.deposit(amount);
        } else {
            System.out.println("Unauthorized access");
        }
    }

    @Override
    public void withdraw(double amount) {
        // 限制admin以外的权限进行取款, 非Admin, 不能调用RealBankAccount取款.
        if (userRole.equals("Admin")) {
            realBankAccount.withdraw(amount);
        } else {
            System.out.println("Unauthorized access");
        }
    }
}

public class BankAccountProxyMain {
    public static void main(String[] args) {
        BankAccount adminAccount = new BankAccountProxy("Admin", 1000);
        adminAccount.deposit(500);
        adminAccount.withdraw(200);

        BankAccount userAccount = new BankAccountProxy("User", 1000);
        userAccount.deposit(500);
        userAccount.withdraw(200); // Will print "Unauthorized access"
    }
}





c++例子

class ISubject{
public:
    virtual void process();
};

class RealSubject: public ISubject{
public:
    virtual void process(){ /* ... */ }
};

class SubjectProxy: public ISubject{
public:
    virtual void process(){ 
        /* 对RealSubject的一种间接访问 */ 
    }
};

// 直接用RealSubject
class ClientApp{
    ISubject* subject;
public:
    ClientApp(){
        subject=new RealSubject();
    }
    void DoTask(){
        subject->process();
        //....
    }
};

// 使用代理模式
class ClientApp{
    ISubject* subject;
public:
    ClientApp(){
        subject=new SubjectProxy();
    }
    void DoTask(){
        subject->process();
    }
};





posted @ 2023-11-26 05:33  qwertzxc  阅读(14)  评论(0)    收藏  举报