设计模式之代理模式(ProxyPattern)

设计模式之代理模式(ProxyPattern)


一.代理模式(ProxyPattern)

代理模式是创建一个代理类,来帮助我们处理真实类,一般来说,这种代理类有点像明星的经纪人,如果你想接触到明星,必须先和他们的经纪人打交道。

注: 接下来为了方便理解类之间的设计关系,采用StartUML画类图,用C++编程

二.编程实例

1.图片读取案例

我们再读取图片文件时,并不会每一次都把它从磁盘中进行读取,而是用一个代理类来判断这个图片是否已经加载过,如果加载过,那就不用从图片中再次读取,可以直接显示。
类图设计
在这里插入图片描述

程序

#include <iostream>
#include <string>
using std::string;
using std::cout;
using std::endl;


/*
设计模式之代理模式:


*/

/************************抽象类**************************/
class Image
{
public:
    virtual void display() = 0;
};

/************************真实类**************************/
class RealImage:public Image
{
public:
    string _filename;
public:
    RealImage(string filename)
    :_filename(filename)
    {
        loadFromDisk();
    }

    void loadFromDisk()
    {
        cout << _filename << "is loading from disk, it may cost some time" << endl;
    }

    void display()
    {
        cout << "display: " << _filename << endl;
    }
};


/************************代理类**************************/
class ProxyImage:public Image
{
public:
    RealImage* _realImage;
    string _filename;

public:
    ProxyImage(string filename)
    :_filename(filename)
    ,_realImage(NULL)
    {}

    void display()
    {
        if (_realImage == NULL)
            _realImage = new RealImage(_filename);
        _realImage->display();
    }
};


int main()
{
    Image *image1 = new ProxyImage("Adult Picture");
    image1->display();
    
    cout << "I want to see Adult Picture again" << endl;
    image1->display();


    return 0;
}

2.String类访问修饰符[]读写操作区分案例

这个案例有一些难度,如果像了解完整的String类实现,可以参考我的另一篇文章:String类COW写时复制技术
在我们重载访问修饰符[]的时候,我们并不能够分清楚它究竟是要进行读操作还是写操作,因为写操作需要重新分配内存而读操作不需要,所以我们用一个代理类来帮助我们进行判断。

程序

#include <iostream>
#include <string>
using std::cout;
using std::endl;
using std::string;


//没有用代理模式
#if 0
class String
{
    char *_pstr;

public:
    String()
        : _pstr(new char[100])
    {
        _pstr[0] = 'a';
    }

    char &operator[](int idx)
    {
        cout << "无法分清读写操作,直接重新分配内存,很消耗时间" << endl;
        _pstr = new char[100];
        _pstr[0] = 'a';
        return _pstr[idx];
    }

    void operator=(const char &ch)
    {
        _pstr[0] = ch;
    }
};
#endif


//使用代理模式
#if 1
class String
{
    char *_pstr;

public:
    //代理类
    class CharProxy
    {
        String &_string;
        int _idx;

    public:
        CharProxy(String &string, int idx)
            : _string(string), _idx(idx)
        {
        }

        //读操作
        operator char()
        {
            return _string._pstr[_idx];
        }

        //写操作
        void operator=(const char &ch)
        {
            cout << "重新分配内存" << endl;
            _string._pstr[_idx] = ch;
        }
    };

public:
    String()
        : _pstr(new char[100])
    {
        _pstr[0] = 'a';
    }

    CharProxy operator[](int idx)
    {
        return CharProxy(*this, idx);
    }

    char *c_str()
    {
        return _pstr;
    }
};
#endif


int main()
{
    String s1;
    cout << s1[0] << endl;
    s1[0] = 'd';

    return 0;
}
  • 1
    点赞
  • 0
    收藏
  • 打赏
    打赏
  • 0
    评论

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

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:深蓝海洋 设计师:CSDN官方博客 返回首页
评论

打赏作者

Worthy_Wang

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

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

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

打赏作者

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

抵扣说明:

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

余额充值