【高级感UP】掌握代理模式,编写优雅而高效的程序,C++实现代理模式揭秘,各种场景的示例代码

已同步到公众号:【蚂蚁博士军团】【码蚁软件】

【高级感UP】掌握代理模式,编写优雅而高效的程序! 

前言:

      今天一起来了解一下结构型设计模式:代理模式

一、原理、示例代码

      代理模式是一种结构型设计模式,它允许你提供一个代理(或者占位符)以控制对其他对象的访问。使用代理模式,一个类代表另一个类的功能。这种类型的设计模式属于结构型模式。

代理模式的主要目的是控制对对象的访问,而不是直接访问它。这种控制可以是对访问的限制,也可以是对访问的增强。

在代理模式中,有三个角色:

  1. Subject(主题):定义了 RealSubject 和 Proxy 的共同接口,这样在任何使用 RealSubject 的地方都可以使用 Proxy。

  2. RealSubject(真实主题):定义了 Proxy 所代表的真实对象。

  3. Proxy(代理):保存一个引用使得代理可以访问实体,并提供一个与 Subject 的接口相同的接口,这样代理可以用来替代实体。

下面是一个使用C++实现的代理模式的示例代码:


#include <iostream>
#include <string>

// 主题接口
class Subject {
public:
    virtual void request() = 0;
};

// 真实主题
class RealSubject : public Subject {
public:
    void request() override {
        std::cout << "RealSubject: Handling request." << std::endl;
    }
};

// 代理
class Proxy : public Subject {
private:
    RealSubject* realSubject;

public:
    void request() override {
        if (realSubject == nullptr) {
            realSubject = new RealSubject();
        }
        std::cout << "Proxy: Logging request." << std::endl;
        realSubject->request();
    }
};

int main() {
    Proxy proxy;
    proxy.request();
    return 0;
}

在上面的示例中,Subject 是主题接口,RealSubject 是真实主题,Proxy 是代理。当客户端调用代理的 request() 方法时,代理会在调用真实主题之前执行日志记录等操作。

二、结构图

代理模式的结构图如下所示:

  +--------------+        +--------------+        +--------------+
  |   Subject    |        |  RealSubject |        |    Proxy     |
  +--------------+        +--------------+        +--------------+
  | +request()   |        | +request()   |        | +request()   |
  +--------------+        +--------------+        +--------------+
                            |              |
                            +--------------+

在这个结构中,Subject 是主题接口,定义了真实主题和代理的公共接口。RealSubject 是真实主题,实现了主题接口,并定义了代理所代表的真实对象。Proxy 是代理,实现了主题接口,并保存了一个指向真实主题的引用,以便可以在需要时访问真实主题。当客户端需要访问真实主题时,可以通过代理来访问。代理可以在访问真实主题之前或之后执行一些额外的操作,例如记录日志、验证权限等。

三、使用场景:

代理模式通常在以下场景中被使用:

  1. 远程代理(Remote Proxy):用于在不同地址空间中代表对象。这种情况下,代理对象充当本地对象的代表,隐藏了远程对象的存在。

  2. 虚拟代理(Virtual Proxy):用于按需创建昂贵对象。当对象的创建和初始化需要大量资源时,可以使用代理对象来延迟对象的创建,直到客户端真正需要使用它时才创建。

  3. 保护代理(Protection Proxy):用于控制对对象的访问。代理可以对客户端的请求进行过滤和验证,以确保客户端有合适的权限来访问真实对象。

  4. 缓存代理(Cache Proxy):用于为开销大的运算结果提供暂时的存储。代理可以在调用真实对象之前检查缓存,如果缓存中存在请求的结果,则直接返回缓存中的数据,否则调用真实对象来计算结果,并将结果存入缓存。

  5. 日志记录(Logging):代理可以在调用真实对象的方法前后进行日志记录,以实现日志功能而不需要修改真实对象的代码。

总之,代理模式适用于需要控制对对象的访问、延迟对象的创建、提供缓存或日志记录等功能的情况。

使用场景的一些示例代码:

下面是一个使用C++实现代理模式进行日志记录的示例代码:

#include <iostream>
#include <string>

// 接口类
class Subject {
public:
    virtual void request() = 0;
};

// 真实主题类
class RealSubject : public Subject {
public:
    void request() override {
        std::cout << "RealSubject: 处理请求" << std::endl;
    }
};

// 代理类
class Proxy : public Subject {
private:
    RealSubject* realSubject;

public:
    Proxy() : realSubject(new RealSubject()) {}

    void request() override {
        // 在调用真实主题前记录日志
        std::cout << "Proxy: 记录日志 - 请求开始" << std::endl;

        // 调用真实主题
        realSubject->request();

        // 在调用真实主题后记录日志
        std::cout << "Proxy: 记录日志 - 请求结束" << std::endl;
    }
};

int main() {
    Proxy proxy;
    proxy.request();

    return 0;
}

在这个示例中,Subject 是一个接口类,RealSubject 是实际的处理类,Proxy 是代理类。当调用 Proxy 的 request 方法时,它会在调用真实主题前后记录日志,然后再调用真实主题的 request 方法来处理请求。这样就实现了代理模式用于日志记录的功能。

下面是一个使用C++实现远程代理的示例代码:

#include <iostream>
#include <string>

// 接口类
class Subject {
public:
    virtual void request() = 0;
};

// 远程主题类
class RemoteSubject : public Subject {
public:
    void request() override {
        std::cout << "RemoteSubject: 处理远程请求" << std::endl;
    }
};

// 代理类
class Proxy : public Subject {
private:
    RemoteSubject* remoteSubject;

public:
    Proxy() : remoteSubject(nullptr) {}

    void request() override {
        if (remoteSubject == nullptr) {
            // 创建远程对象
            remoteSubject = new RemoteSubject();
        }

        // 在调用远程主题前进行网络连接等操作
        std::cout << "Proxy: 进行网络连接" << std::endl;

        // 调用远程主题
        remoteSubject->request();

        // 在调用远程主题后进行网络关闭等操作
        std::cout << "Proxy: 关闭网络连接" << std::endl;
    }
};

int main() {
    Proxy proxy;
    proxy.request();

    return 0;
}

在这个示例中,Subject 是一个接口类,RemoteSubject 是远程的处理类,Proxy 是代理类。当调用 Proxy 的 request 方法时,它会在调用远程主题前进行网络连接等操作,然后调用远程主题的 request 方法来处理远程请求,最后再进行网络关闭等操作。这样就实现了代理模式中的远程代理功能。

下面是一个使用C++实现代理模式的示例代码,演示了虚拟代理的场景:

#include <iostream>
#include <string>

// 接口类
class Image {
public:
    virtual void display() = 0;
};

// 真实主题类
class RealImage : public Image {
private:
    std::string filename;

public:
    RealImage(const std::string& filename) : filename(filename) {
        // 模拟加载图片的过程
        std::cout << "RealImage: 加载图片 " << filename << std::endl;
    }

    void display() override {
        std::cout << "RealImage: 显示图片 " << filename << std::endl;
    }
};

// 代理类
class ProxyImage : public Image {
private:
    std::string filename;
    RealImage* realImage;

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

    void display() override {
        if (realImage == nullptr) {
            // 创建真实图片对象
            realImage = new RealImage(filename);
        }
        realImage->display();
    }
};

int main() {
    // 使用代理对象加载和显示图片
    Image* image = new ProxyImage("example.jpg");
    image->display();

    return 0;
}

在这个示例中,Image 是一个接口类,RealImage 是真实的图片处理类,ProxyImage 是代理类。当创建 ProxyImage 对象时,并调用 display 方法时,它会在需要显示图片时才去创建真实的图片对象,从而实现了虚拟代理的延迟加载功能。

下面是一个使用C++实现保护代理的示例代码,演示了保护代理的场景:

#include <iostream>
#include <string>

// 接口类
class Door {
public:
    virtual void open() = 0;
    virtual void close() = 0;
};

// 真实主题类
class RealDoor : public Door {
public:
    void open() override {
        std::cout << "RealDoor: 打开门" << std::endl;
    }

    void close() override {
        std::cout << "RealDoor: 关闭门" << std::endl;
    }
};

// 代理类
class SecurityDoor : public Door {
private:
    RealDoor* realDoor;
    bool isAdmin;

public:
    SecurityDoor(bool isAdmin) : realDoor(new RealDoor()), isAdmin(isAdmin) {}

    void open() override {
        if (isAdmin) {
            realDoor->open();
        } else {
            std::cout << "SecurityDoor: 没有权限打开门" << std::endl;
        }
    }

    void close() override {
        if (isAdmin) {
            realDoor->close();
        } else {
            std::cout << "SecurityDoor: 没有权限关闭门" << std::endl;
        }
    }
};

int main() {
    // 创建安全门对象
    Door* door = new SecurityDoor(true); // 使用管理员权限
    door->open();
    door->close();

    Door* guestDoor = new SecurityDoor(false); // 使用普通访客权限
    guestDoor->open();
    guestDoor->close();

    return 0;
}

在这个示例中,Door 是一个接口类,RealDoor 是真实的门处理类,SecurityDoor 是代理类。在 SecurityDoor 中,根据权限的不同,决定是否允许打开或关闭门。当使用管理员权限时,可以打开和关闭门;当使用普通访客权限时,无法打开或关闭门,从而实现了保护代理的功能。

四、优缺点:

    优点:

  1. 代理模式可以实现对真实主题的远程控制,例如在网络上的远程代理。

  2. 代理模式可以实现对真实主题的保护,例如控制对真实主题的访问权限。

  3. 代理模式可以实现对真实主题的增强,例如在调用真实主题的方法前后进行一些额外的操作。

    缺点:

  1. 增加了系统复杂性,因为引入了代理对象。

  2. 由于在代理模式中会引入代理对象,可能会导致请求的处理速度变慢。

      欢迎有更多朋友一起探讨技术哈,评论区留言~

  • 20
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

五木大大

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值