代理模式(Proxy)

设计模式系列

Proxy代理模式——对象结构模式

1.意图

为其他对象提供一种代理以控制对这个对象的访问。

 

2.适用性

在需要用比较通用和复杂的对象指针代替简单的指针的时候,使用Proxy模式。

1)远程代理(Remote Proxy)为一个对象在不同的地址空间提供局部代表。

2)虚代理(Virtual Proxy)根据需要创建开销很大的对象。

3)保护代理(Protection Proxy)控制对原始对象的访问。保护代理用于对象应该用不同的访问权限的时候。

4)智能指引(Smart Reference)取代了简单的指针,它在访问对象时执行一些附加操作。它的典型用途包括 :

  • 对指向实际对象的引用计数,这样当该对象没有引用时,可以自动释放它(也称为Smart Pointers(智能指针))
  • 当第一次引用一个持久对象时,将它装入内存
  • 在访问一个实际对象前,检查是否已经锁定了它,以确保其他对象不能改变它。

 

3.结构

 

4.参与者

  • Proxy

—— 保存一个引用使得代理可以访问实体。若RealSubject和Subject的接口相同,Proxy会引用Subject.

—— 提供一个与Subject的接口相同的接口,这样代理就可以用来替代实体

—— 控制对实体的存取,并可能负责创建和删除它

—— 其他功能依赖于代理的类型:

  1. Remote Proxy负责对请求及其参数进行编码,并向不同地址空间中的实体发送已编码的请求

  2. Virtual Proxy可以缓存实体的附加信息,以便延迟对它的访问。

  3. Protection Proxy检查调用者是否具有实现一个请求所必需的访问权限。

  • Subject

—— 定义RealSubject和Proxy的共用接口,这样就在任何使用RealSubject的地方都可以使用Proxy。

  • RealSubject

—— 定义Proxy所代表的实体

 

5.案例

 

#include <iostream>
using namespace std;
template <class T>
class Auto_Ptr;

//智能指针和引用计数
template <class T>
class Ref_Ptr 
{
    friend class Auto_Ptr<T>;
private:
    T* m_pTtr;//实际的指针
    size_t m_RefCount;//引用计数
    Ref_Ptr(T* p);
    virtual ~Ref_Ptr();
};

template<class T>
Ref_Ptr<T>::Ref_Ptr(T* p) 
{
    m_pTtr = p;
    m_RefCount = 1;
    cout << "Ref_Ptr()构造函数调用" << endl;
}

template<class T>
Ref_Ptr<T>::~Ref_Ptr() 
{
    if (m_pTtr) 
    {
        cout << "~Ref_Ptr()析构函数调用" << endl;
        delete m_pTtr;
        m_pTtr = nullptr;
        m_RefCount = 0;
    }

    m_pTtr = nullptr;
}

//智能指针对象
template<class T>
class Auto_Ptr 
{
public:
    Auto_Ptr();
    Auto_Ptr(T* p);
    ~Auto_Ptr();
    //运算符重载
    Auto_Ptr<T>& operator = (Auto_Ptr& other);
    T& operator *();
    T* operator ->();
    //拷贝构造函数
    Auto_Ptr(Auto_Ptr<T>& other);
private:
    Ref_Ptr<T>* m_pRef;
};

template<class T>
Auto_Ptr<T>::Auto_Ptr() { m_pRef = nullptr; }

template<class T>
Auto_Ptr<T>::Auto_Ptr(T* p) 
{
    m_pRef = new Ref_Ptr<T>(p);
    cout << "Auto_ptr(T* p)构造函数调用" << endl;
}

template<class T>
Auto_Ptr<T>::Auto_Ptr(Auto_Ptr<T>& other) 
{
    m_pRef = other.m_pRef;
    ++(m_pRef->m_RefCount);
    cout << "Auto_ptr(& other)拷贝构造函数调用" << endl;
}

template<class T>
Auto_Ptr<T>& Auto_Ptr<T>::operator=(Auto_Ptr& other) 
{
    //将右操作数对应引用+1
    ++(other.m_pRef->m_RefCount);
    //由于左操作数指向了新对象,所以将操作数-1
    //防止自赋值
    if (m_pRef) 
    {
        if (--(m_pRef->m_RefCount) == 0) { delete m_pRef; }
    }
    m_pRef = other.m_pRef;
    printf("operator = 被调用,当前的引用计数:%d", m_pRef->m_RefCount);
    return *this;
}

template <class T>
T& Auto_Ptr<T>::operator*() { return *(m_pRef->m_pTtr); }

template <class T>
T* Auto_Ptr<T>::operator->() { return (m_pRef->m_pTtr); }

template <class T>
Auto_Ptr<T>::~Auto_Ptr() 
{
    cout << "析构函数在调用" << endl;
    if ((--m_pRef->m_RefCount) == 0) 
    {
        cout << "删除" << endl;
        delete m_pRef;
        m_pRef = nullptr;
    }
}

int main(void) 
{
    Auto_Ptr<int>* pPtr = nullptr;
    {
        Auto_Ptr<int> g_ptr;
        {
            //声明一个ptr1的智能指针
            Auto_Ptr<int> ptr1(new int(4));
            printf("%d\n", *ptr1);
            //将生存期小的ptr1赋值给生存期更大的g_ptr;
            g_ptr = ptr1;
        }
        //new int(4)没有销毁
        Auto_Ptr<int> ptr2(new int(3));
        g_ptr = ptr2;//g-ptr --> 新的智能指针 
        Auto_Ptr<int>* pPtr = &ptr2;
        printf("%d\n", *(*pPtr));
    }
    system("pause");
    return 0;
}

设计模式系列 https://blog.csdn.net/nie2314550441/article/details/105849726

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值