• 设计模式 笔记 代理模式 Proxy





    //---------------------------15/04/21----------------------------



    //Proxy 代理模式-----对象结构型模式

    /*

        1:意图:

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

        2:别名:

            Surrogate

        3:动机:

        4:适用性:

            1>远程代理:

                为一个对象在不同的地址空间提供局部代表。

            2>虚代理:

                根据需要创建开销很大的对象。

            3>保护代理:

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

            4>指针指引:

                取代简单的指针,它在访问对象时执行一些附加操作:

                    1)统计指向实际对象的引用次数,这样对象没有引用时可以自动释放。(智能指针)

                    2)当第一次引用一个持久对象时,将它装入内存。(懒加载)

                    3)在访问一个实际对象前,检查是否已经锁定了它,保证其他对象不能改变它。(多线程加锁)

        5:结构:

            Client------------->Subject:

                                Request()

                                    |

                                    |

                        -------------------

                        |                 |

                        |               Proxy:

                    RealSubject:<-------realSubject

                    Request()           Request()

                                        {...

                                            realSubject->Request();

                                         ...}

        6:参与者:

            1>Proxy:

                1)保存一个引用使得代理可以访问实体

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

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

                4)其他功能以来于代理的类型:

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

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

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

            2>Subjet

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

            3>RealSubject

                定义Proxy所代表的实体。

        7:协作:

            代理根据其种类,在适当的时候向RealSubject转发请求。

        8:效果:

            1>Remote Proxy可以隐藏一个对象存在于不同地址空间的事实。

            2>Virtual Proxy可以进行最优化,例如根据要求创建对象。

            3>Protecition Proxies Smart Reference都允许在访问一个对象时有一些附加的内务处理。

            4>Copyonwirte

                拷贝一个庞大的对象是开销很大的操作,如果这个拷贝没有被修改,那么这些开销就没必要,所以可以使用

                代理,来延迟拷贝的动作,一开始代理只增加实体一个引用计数,当用户需要修改这份拷贝时,再真正执行

                拷贝动作,并减少引用计数。

        9:实现:

            1>重载C++中的存取运算符

                C++支持重载->*运算符。所以重载这两个操作符来加载真正的对象,在没有使用前(没调用这两个操作符前)

                我们可以不用加载。

            2>Proxy并不总是需要知道实体的类型。

                1)不需要实例化实体时。并不需要为具体的RealSubject类生成特定的Proxy类;Proxy类可以统一处理

                  所有的这样的RealSubject类。

                2)需要实例化实体时。在实例化之前,可以使用某种特定的标识符来表示实体,比如文件路径。

        10:代码示例:                                                                            */


    //Subject类,定义了RealSubjectProxy的接口

    class Graphic

    {

    public:

        virtual ~Graphic();

        virtual void Draw(const Point& at) = 0;

        virtual void HandleMouse(Event& event)= 0;

        virtual const Point& GetExtent()= 0;

        virtual void Load(istream& form)= 0;

        virtual void Save(ostrean& to)= 0;

        

    protected:

        Graphic();

    };


    //RealSubject

    class Image : public Graphic

    {

    public:

        Image(const char* file);

        virtual ~Image();

        virtual void Draw(const Point& at);

        virtual void HandleMouse(Event& event);

        virtual const Point& GetExtent();

        virtual void Load(istream& form);

        virtual void Save(ostrean& to);

    private:

        ...

    };


    //Proxy

    class ImageProxy : public Graphic

    {

    public:

        ImageProxy(const char* file);

        virtual ~ImageProxy();

        virtual void Draw(const Point& at);

        virtual void HandleMouse(Event& event);

        virtual const Point& GetExtent();

        virtual void Load(istream& form);

        virtual void Save(ostrean& to);

    protected:

        Image* GetImage();

    private:

        Image* _image;

        Point _extent;

        char* fileName;

    };


    //构造函数,接受一个fileName(cosnst char*)参数

    ImageProxy::ImageProxy(const char* fileName)

    {

        _fileName = strdup(fileName);

        _extent = Point::Zero;

        _image = 0;

    }


    //只有这时才会真正创建出Image

    Image* ImageProxy::GetImage()

    {

        if(_image == 0)

        {

            _image = new Image(_fileName);

        }

        return _image;

    }


    //如果已经缓存过,就直接返回_exyent

    const Point& ImageProxy::GetExtent()

    {

        if(_extent == Point::Zero)

            _extent = GetImage()->GetExtent();

        return _extent;

    }


    //实现继承的接口

    void ImageProxy::Draw(const Point& at)

    {

        GetImage()->Draw(at);

    }


    void ImageProxy::HandleMouse(Event& event)

    {

        GetImage()->HandleMouse(event);

    }


    void ImageProxy::Save(ostrean& to)

    {

        to<< _extent << _fileName;

    }


    void ImageProxy::Load(istream& from)

    {

        from >> _extent >> _fileName;

    }


    class TextDocument

    {

    public:

        TextDocument();

        void Insert(Graphic*);

    };


    //如何使用

    TextDocument* text = new TextDocument;


    text->Insert(new ImageProxy("naImageFileName"));



  • 相关阅读:
    UI自动化测试模型
    Selenium:HTML测试报告
    Selenium:浏览器及鼠标、键盘事件
    Selenium:WebDriver简介及元素定位
    selenium自动化环境搭建(Windows)
    浅谈UI自动化测试
    《MySQL:菜鸟入门系列》
    《HTTP协议:菜鸟入门系列》
    人人都是产品经理<1.0>
    聊聊连接池和线程
  • 原文地址:https://www.cnblogs.com/boydfd/p/4983129.html
Copyright © 2020-2023  润新知