zoukankan      html  css  js  c++  java
  • 设计模式 笔记 代理模式 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"));



  • 相关阅读:
    买房的贷款时间是否是越长越好?https://www.zhihu.com/question/20842791
    asp.net cookie and session
    leelazero and google colab
    download file by python in google colab
    physical processor, core, logical processor
    通过powershell操作eventlog
    openxml in sql server
    get the page name from url
    How to Execute Page_Load() in Page's Base Class?
    Difference between HttpContext.Request and Request
  • 原文地址:https://www.cnblogs.com/boydfd/p/4983129.html
Copyright © 2011-2022 走看看