码迷,mamicode.com
首页 > 其他好文 > 详细

设计模式 笔记 代理模式 Proxy

时间:2015-04-21 20:49:51      阅读:158      评论:0      收藏:0      [点我收藏+]

标签:设计模式   笔记   代理模式   




//---------------------------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"));



设计模式 笔记 代理模式 Proxy

标签:设计模式   笔记   代理模式   

原文地址:http://blog.csdn.net/boydfd/article/details/45174589

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!