前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >C++设计模式——Proxy代理模式

C++设计模式——Proxy代理模式

作者头像
Coder-ZZ
发布2024-06-18 15:29:46
1220
发布2024-06-18 15:29:46
举报
文章被收录于专栏:C/C++进阶专栏C/C++进阶专栏

一,代理模式简介

代理模式是一种结构型设计模式,该模式通过引入一个新的代理对象Proxy,来间接访问原始对象,从而使访问方式变得灵活和可控。

代理对象的设定减少了客户端与真实对象之间的直接交互。

通过引入代理对象来间接访问原始的对象,达到延迟访问和隔离的效果,这就是代理模式的主要用途。

举个例子:

当有多个客户端对数据库发起大批量请求时,数据库由于需要同时处理多个请求,导致其处理速度变得很慢。

此时如果有一个代理,用法上和数据库一致,这个代理先收集来自多个客户端的请求,进行缓存,然后逐渐转发给数据库,避免了通道发生阻塞,那么数据库此时的处理速度会大大提升。

二,代理模式的结构

1.抽象对象(Subject):定义了真实对象和代理对象的共同接口。

2.真实对象(RealSubject):又称为被代理对象,代理模式中的核心角色,定义了真正需要被代理的业务逻辑。

3.代理对象(Proxy):充当了客户端与真实对象之间的中介。

对应UML类图:

1.Subject定义了Proxy和RealSubject的公共接口。

2.Proxy和RealSubject都实现了Subject的接口。

3.客户端(Client)通过Proxy与RealSubject进行交互。

4.RealSubject负责完成主要的接口实现,Proxy负责控制外部Client对接口的访问。

5.Proxy内部包含对Subject的对象指针或引用,因此Proxy可以进一步调用子类RealSubject中的函数(forward calls)。

6.在某些情况下,Proxy可以用来完成RealSubject实例的创建与销毁。

7.Client是使用Proxy的对象,它通过Proxy来访问和操作RealSubject。

代码实现:

代码语言:javascript
复制
#include <iostream>
using namespace std;

class Subject
{
public:
       virtual void request() = 0;
       virtual ~Subject() {}
};

class RealSubject : public Subject
{
public:
       void request() {
          cout << "RealSubject.request()" << endl;
       }
};

class Proxy : public Subject
{
private:
       Subject* realSubject;
public:
       Proxy()
       {
              realSubject = new RealSubject();
       }
       ~Proxy()
       {
              delete realSubject;
       }
       // Forward calls to the RealSubject:
       void request() {
              realSubject->request();
       }
};

int main() {
       Proxy p;
       p.request();
}

运行结果:

代码语言:javascript
复制
RealSubject.request()

补充:在C++编码中,确实可以通过继承和虚函数实现父类调用子类的成员函数,这是C++多态特性的一种常见应用方式。

代码样例:

代码语言:javascript
复制
#include <iostream>
using namespace std;

class Base {
public:
    virtual void print() { 
        cout << "Base class method" << endl; 
    }
};

class Derived : public Base {
public:
    // 重写父类的虚函数
    virtual void print() override { 
       cout << "Derived class method" << endl;  
    }
};

int main() {
    // 父类对象调用子类方法
    Base* baseObj = new Derived();
    baseObj->print();
}

运行结果:

代码语言:javascript
复制
Derived class method

三,代理模式的种类

简单代理(Simple Proxy):主要用于转发请求和处理一些基本操作,例如添加日志、计时等。

远程代理(Remote Proxy):当主体对象在另一个地址空间(如网络地址)时,远程代理会提供远程通信的功能,进行数据的访问和转换。

智能引用代理(Smart Reference Proxy):也称为共享代理,它维护了多个客户端对同一目标的共享引用,并提供统一的接口。

虚拟代理(Virtual Proxy):延迟针对昂贵资源的访问,只有在真正使用时才加载。

保护代理(Protection Proxy):主要用于访问权限的控制,比如身份验证、授权等。

四,代理模式的应用场景

1.延迟加载:使资源密集型的对象仅仅在被使用时才加载,例如,访问大型数据库、加载大批量图像数据等。

2.访问控制:代理可以通过添加身份验证来控制对真实主体的访问,可用于保护敏感数据。

3.缓存机制:代理可以缓存高频次的请求,从而减少系统开销,优化性能。

4.日志记录和监控:代理可用于记录或监控对真实主体执行的操作,而无需修改其代码。

5.远程访问:在分布式系统中,真实主体可能位于不同的计算机上,代理模式可以隐藏远程通信的复杂细节。

6.状态管理:代理可以同步管理多个客户端所共享的真实主体的状态,确保它们的一致性。

五,代理模式的优缺点

代理模式的优点:

可以在不修改被代理对象的情况下,增加额外的功能或控制访问方式。

可以在访问对象之前和之后进行一些处理,比如添加日志、添加时间戳等。

可以实现远程代理,使得客户端可以通过网络访问远程的对象。

可以防止未经授权访问真实主体。

代理模式的缺点:

引入新的类,增加代码复杂性。

读取资源时,需要通过代理来间接访问,造成额外的性能损失。

六,代码实战

开发场景:基于Proxy模式来模拟对图片的延迟加载和显示控制。

1.创建Subject

代码语言:javascript
复制
//Step 1: Define the Subject interface
class Image {
public:
    virtual void display() = 0;
};

2.创建RealSubject

代码语言:javascript
复制
//Step 2: Implement the Real Object
class RealImage : public Image {
private:
    std::string filename;
public:
    RealImage(const std::string& filename) : filename(filename) {
        // Simulate loading the image 
        std::cout << "Loading image: " << filename << std::endl;
    }

    void display() override {
        std::cout << "Displaying image: " << filename << std::endl;
    }
};

3.Proxy类实现与RealSubject相同的接口,并维护对RealSubject的引用。

代码语言:javascript
复制
//Step 3: Create the Proxy
class ImageProxy : public Image {
private:
    // Reference to the Real Object
    RealImage* realImage;
    std::string filename;

public:
    ImageProxy(const std::string& filename) : filename(filename), realImage(nullptr) {}

    void display() override {
        if (realImage == nullptr) {
            realImage = new RealImage(filename);
        }
        realImage->display();
    }
};

完整代码实现:

代码语言:javascript
复制
#include <iostream>
#include <bits/stdc++.h>

using namespace std;
class Image {
public:
    virtual void display() = 0;
};

class RealImage : public Image {
private:
    std::string filename;
public:
    RealImage(const std::string& filename) : filename(filename) {
        // Simulate loading the image
        std::cout << "Loading image: " << filename << std::endl;
    }

    void display() override {
        std::cout << "Displaying image: " << filename << std::endl;
    }
};

class ImageProxy : public Image {
private:
    // Reference to the Real Object
    RealImage* realImage; 
    std::string filename;

public:
    ImageProxy(const std::string& filename) : filename(filename), realImage(nullptr) {}

    void display() override {
        if (realImage == nullptr) {
            realImage = new RealImage(filename);
        }
        realImage->display();
    }
};

int main() {
    //Create a proxy to an image
    Image* image = new ImageProxy("example.jpg");

    //Display the image
    image->display();

    //Displaying the image again
    image->display();

    delete image;
    return 0;
}

运行结果:

代码语言:javascript
复制
Loading image: example.jpg
Displaying image: example.jpg
Displaying image: example.jpg

七,参考阅读

https://www.geeksforgeeks.org/proxy-pattern-c-design-patterns/

https://www.bogotobogo.com/DesignPatterns/proxy.php

https://design-patterns.readthedocs.io/zh-cn/latest/structural_patterns/proxy.html

https://refactoring.guru/design-patterns/proxy

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2024-06-12,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 程序员与背包客 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
多因子身份认证
多因子身份认证(Multi-factor Authentication Service,MFAS)的目的是建立一个多层次的防御体系,通过结合两种或三种认证因子(基于记忆的/基于持有物的/基于生物特征的认证因子)验证访问者的身份,使系统或资源更加安全。攻击者即使破解单一因子(如口令、人脸),应用的安全依然可以得到保障。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档