C++设计模式——代理模式(Proxy Pattern)

C++设计模式——代理模式(Proxy Pattern)

微信公众号:幼儿园的学霸

目录

定义

The proxy design pattern allows you to provide an interface to other objects by creating a wrapper class as the proxy. The wrapper class, which is the proxy, can add additional functionality to the object of interest without changing the object’s code.

代理模式又叫委托模式,是为某个对象提供一个代理对象,并且由代理对象控制对原对象的访问。代理模式通俗来讲就是我们生活中常见的中介。

由于某些原因,一个类(A)不能直接被客户端使用,所以我们可以创建这个类的代理类(B),实际上B就是A的影子而已

在代理模式(Proxy Pattern)中,一个类代表另一个类的功能。这种类型的设计模式属于结构型模式。
代理模式中的角色如下:

  • 抽象主题角色(Subject):可以是抽象类,也可以是接口。定义真实主题角色RealSubject 和 抽象主题角色Proxy的共用接口,这样就在任何使用RealSubject的地方都可以使
    用Proxy。
  • 具体主题角色(RealSubject):也叫做被委托角色或被代理角色,是业务逻辑的具体执行者。定义了代理角色(proxy)所代表的具体对象
  • 代理主题角色(Proxy):也叫做委托类或代理类。它负责对真实角色的应用,把所有抽象主题类定义的方法限制委托给真实主题角色实现,并且在具体主题角色处理完毕前后做预处理和善后处理工作。

其类图如下:
代理模式类图

一个代理类可以代理多个被委托者或被代理者,因此一个代理类具体代理哪个具体主题角色,是由场景类决定的。最简单的情况是一个主题类和一个代理类。通常情况下,一个接口只需要一个代理类,具体代理哪个实现类由高层模块决定。

代码示例

以代理服务器为例进行代码编写,访问真正的服务器,需要通过代理服务器,代理服务器进行用户名密码校验,通过才允许访问真实服务器。


#include <bits/stdc++.h>

//抽象类,抽象的主题类
class AbstractServer {
public:
    virtual void Request() = 0;

    virtual ~AbstractServer() = default;
};

//真正主题类,具体提供服务的类
class RealServer : public AbstractServer {
    void Request() override {
        std::cout << "服务器启动..." << std::endl;
    }

};

//代理服务器,非真正的服务器,访问真正服务器必须通过代理服务器
class ProxyServer : public AbstractServer {
public:
    ProxyServer(const std::string &name, const std::string &pwd)
            : m_name(name), m_pwd(pwd) {
        m_pserver = std::make_shared<RealServer>();
    }

    // 和 真正主题类实现共同的接口,对外可以提供一致的接口!
    void Request() override {
        if (!CheckUser()) {
            std::cout << "用户名或者密码错误..." << std::endl;
            return;
        }
        std::cout << "校验用户名及密码成功..." << std::endl;
        PreRequest();//额外附加的操作

        m_pserver->Request();

        PostRequest();//额外附加的操作
    }

private:
    //访问服务器前 进行的动作,可以控制对真实主题类的访问
    bool CheckUser() {
        if ("admin" == m_name && "123456" == m_pwd) {
            return true;
        }
        return false;
    }

    //真正访问服务器前 进行的动作
    void PreRequest() {
        std::cout << "进入代理服务器..." << std::endl;
    }

    //访问服务器之后 进行的动作
    void PostRequest() {
        std::cout << "服务器访问完毕..." << std::endl;
    }


private:
    std::shared_ptr<AbstractServer> m_pserver;
    std::string m_name;
    std::string m_pwd;
};

//客户端 通过登录代理服务器 访问 真实服务器
int main(int argc, char *argv[]) {
    std::shared_ptr<AbstractServer> proxy = std::make_shared<ProxyServer>("admin", "123456");//登录代理服务器
    proxy->Request();//通过代理服务器 访问真正服务器

    return 0;
    //运行结果如下:
    //校验用户名及密码成功...
    //进入代理服务器...
    //服务器启动...
    //服务器访问完毕...
}

先访问代理类再访问真正要访问的对象。似乎这样有点多此一举的味道,其实不然。代理类可以在真正的类执行之前,进行预处理。
在比如你有一个系统实现了登陆功能,在用户登录时,真正的登录类和代理登录类都实现了Login接口, 不同的是Proxy类的方法中增加了用户是否合法的判断,只有合法时才去调用真正登录类的login方法. 用户访问的其实是Proxy的login方法.这都是代理模式的优点。而且采用代理模式的话,并且你可以随时更改代理。

总结

优缺点

  • 优点:
    1.职责清晰。 2.高扩展性。 3.智能化。
  • 缺点:
    1.由于在客户端和真实主题之间增加了代理对象,因此有些类型的代理模式可能会造成请求的处理速度变慢。 2.实现代理模式需要额外的工作,有些代理模式的实现非常复杂。

对比

  • 代理模式与外观模式:
    1.代理模式中的代理角色和真实角色都继承于同一类。而外观模式是多个类的集合。
    2.代理角色与真实角色接口相同,功能一致,代理角色实现的是真实角色的功能。外观者模式的子系统功能不同,根据用户不同需要与外观类统一配置。
    3.实现方式上,外观模式是产生一个新类,封装内部操作;代理是产生一个继承类,操作对用户看起来是一样的。

  • 代理模式与适配器模式
    适配器模式主要改变所考虑对象的接口,使得原本由于接口不兼容而不能一起工作的那些类可以一起工作,大多用在代码维护的后期,或者借用第三方库的情况下;而代理模式不能改变所代理类的接口。

  • 代理模式与装饰模式
    装饰器模式为了增强功能,而代理模式是为了加以控制。 (该部分区别在装饰模式有所阐述)

代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后对返回结果的处理等。代理类本身并不真正实现服务,而是通过调用委托类的相关方法,来提供特定的服务。真正的业务功能还是由委托类来实现,但是可以在业务功能执行的前后加入一些公共的服务。

智能指针的引用计数实现,应该就是采用代理模式实现的。个人看法。

参考资料

1.代理模式
2.设计模式之——代理模式
3.设计模式:代理模式(C++)【代理服务器案例】



下面的是我的公众号二维码图片,欢迎关注。
图注:幼儿园的学霸

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值