代理模式(Proxy Pattern)及其应用场景

代理模式是一种结构型设计模式,它为其他对象提供一种代理以控制对这个对象的访问。代理对象在客户端和目标对象之间起到中介作用,可以在不改变原始类代码的情况下增加额外的功能。

代理模式的特点

  1. 控制访问:控制对真实对象的访问

  2. 附加功能:可以在访问真实对象前后添加额外操作

  3. 延迟初始化:可以推迟昂贵对象的创建直到真正需要时

  4. 远程代理:可以代表位于不同地址空间的对象

代理模式的类型

  1. 虚拟代理:延迟创建开销大的对象

  2. 保护代理:控制对原始对象的访问权限

  3. 远程代理:为远程对象提供本地代表

  4. 智能引用:在访问对象时执行额外操作(如引用计数)

典型应用场景

  1. 延迟初始化(虚拟代理)

  2. 访问控制(保护代理)

  3. 本地代表远程对象(远程代理)

  4. 日志记录、缓存等附加功能

  5. 对敏感对象的保护

  6. 引用计数和内存管理

C++ 示例程序

示例1:虚拟代理(图像加载)

#include <iostream>
#include <string>
#include <memory>

// 抽象主题
class Image {
public:
    virtual ~Image() = default;
    virtual void display() = 0;
};

// 真实主题
class RealImage : public Image {
private:
    std::string filename;
    
    void loadFromDisk() {
        std::cout << "Loading image: " << filename << " from disk (expensive operation)\n";
    }
    
public:
    RealImage(const std::string& filename) : filename(filename) {
        loadFromDisk();
    }
    
    void display() override {
        std::cout << "Displaying image: " << filename << "\n";
    }
};

// 代理类
class ImageProxy : public Image {
private:
    std::string filename;
    std::unique_ptr<RealImage> realImage;
    
public:
    ImageProxy(const std::string& filename) : filename(filename) {}
    
    void display() override {
        if (!realImage) {
            realImage = std::make_unique<RealImage>(filename); // 延迟初始化
        }
        realImage->display();
    }
};

// 客户端代码
int main() {
    std::cout << "--- Using Proxy ---\n";
    ImageProxy proxy("test_image.jpg");
    
    // 图像尚未加载
    std::cout << "Image not loaded yet\n";
    
    // 第一次显示 - 加载图像
    std::cout << "First display:\n";
    proxy.display();
    
    // 第二次显示 - 图像已加载,直接使用
    std::cout << "Second display:\n";
    proxy.display();
    
    return 0;
}

示例2:保护代理(访问控制)

#include <iostream>
#include <string>
#include <memory>

// 抽象主题
class Database {
public:
    virtual ~Database() = default;
    virtual void query(const std::string& sql) = 0;
};

// 真实主题
class RealDatabase : public Database {
public:
    void query(const std::string& sql) override {
        std::cout << "Executing query: " << sql << "\n";
        // 实际执行数据库查询...
    }
};

// 代理类
class DatabaseProxy : public Database {
private:
    std::unique_ptr<RealDatabase> realDb;
    std::string userRole;
    
    bool hasAccess() const {
        return userRole == "admin";
    }
    
public:
    DatabaseProxy(const std::string& role) : userRole(role) {}
    
    void query(const std::string& sql) override {
        if (!hasAccess()) {
            std::cout << "Access denied for role: " << userRole << "\n";
            return;
        }
        
        if (!realDb) {
            realDb = std::make_unique<RealDatabase>();
        }
        
        std::cout << "Log: User " << userRole << " executed query\n";
        realDb->query(sql);
    }
};

// 客户端代码
int main() {
    std::cout << "--- Admin Access ---\n";
    DatabaseProxy adminProxy("admin");
    adminProxy.query("SELECT * FROM users");
    
    std::cout << "\n--- Guest Access ---\n";
    DatabaseProxy guestProxy("guest");
    guestProxy.query("DROP TABLE users");
    
    return 0;
}

示例3:智能引用代理(带引用计数)

#include <iostream>
#include <memory>
#include <vector>

// 大型资源类
class ExpensiveResource {
public:
    ExpensiveResource() {
        std::cout << "Creating expensive resource (high memory usage)\n";
    }
    
    ~ExpensiveResource() {
        std::cout << "Destroying expensive resource\n";
    }
    
    void operation() {
        std::cout << "Performing operation on expensive resource\n";
    }
};

// 智能引用代理
class ResourceProxy {
private:
    static ExpensiveResource* realResource;
    static int refCount;
    
public:
    ResourceProxy() {
        if (refCount == 0) {
            realResource = new ExpensiveResource();
        }
        refCount++;
        std::cout << "Resource reference count: " << refCount << "\n";
    }
    
    ~ResourceProxy() {
        refCount--;
        std::cout << "Resource reference count: " << refCount << "\n";
        if (refCount == 0 && realResource != nullptr) {
            delete realResource;
            realResource = nullptr;
        }
    }
    
    ExpensiveResource* operator->() const {
        return realResource;
    }
};

// 静态成员初始化
ExpensiveResource* ResourceProxy::realResource = nullptr;
int ResourceProxy::refCount = 0;

// 客户端代码
int main() {
    std::cout << "--- Using ResourceProxy ---\n";
    
    {
        ResourceProxy proxy1;
        proxy1->operation();
        
        {
            ResourceProxy proxy2;
            proxy2->operation();
            
            ResourceProxy proxy3;
            proxy3->operation();
        } // proxy2和proxy3离开作用域
        
        proxy1->operation();
    } // proxy1离开作用域
    
    return 0;
}

示例4:远程代理(模拟)

#include <iostream>
#include <string>
#include <memory>

// 远程服务接口
class PaymentService {
public:
    virtual ~PaymentService() = default;
    virtual bool processPayment(const std::string& account, double amount) = 0;
};

// 远程服务实现(模拟)
class RemotePaymentService : public PaymentService {
public:
    bool processPayment(const std::string& account, double amount) override {
        // 模拟远程调用
        std::cout << "Connecting to remote payment server...\n";
        std::cout << "Processing payment of $" << amount << " to account " << account << "\n";
        // 模拟网络延迟
        std::cout << "Waiting for response...\n";
        return true; // 假设总是成功
    }
};

// 远程代理
class PaymentServiceProxy : public PaymentService {
private:
    std::unique_ptr<RemotePaymentService> realService;
    
public:
    bool processPayment(const std::string& account, double amount) override {
        if (!realService) {
            realService = std::make_unique<RemotePaymentService>();
        }
        
        // 可以在这里添加缓存、日志等功能
        std::cout << "Proxy: Logging payment request - " 
                  << account << ", $" << amount << "\n";
        
        bool result = realService->processPayment(account, amount);
        
        std::cout << "Proxy: Payment processed, result: " 
                  << (result ? "success" : "failure") << "\n";
        return result;
    }
};

// 客户端代码
int main() {
    std::cout << "--- Using Payment Proxy ---\n";
    PaymentServiceProxy proxy;
    
    proxy.processPayment("ACCT-12345", 100.0);
    proxy.processPayment("ACCT-67890", 250.0);
    
    return 0;
}

总结

代理模式通过引入一个代理对象来控制对原始对象的访问,其主要优点包括:

  1. 控制访问:可以在访问对象前后添加额外操作

  2. 延迟初始化:对于资源密集型对象,可以推迟创建直到真正需要时

  3. 远程代理:可以简化远程对象的访问

  4. 保护机制:可以增加权限检查等安全层

代理模式与装饰器模式的区别在于:

  • 代理控制访问,通常管理其服务对象的生命周期

  • 装饰器为对象添加行为,通常不控制对象的生命周期

在实际应用中,代理模式常用于:

  • 延迟加载大型资源

  • 实现访问控制

  • 本地代表远程服务

  • 添加日志、缓存等横切关注点

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值