C++设计模式8–代理模式–万能的中间层

作者: veaxen 分类: 设计模式 发布时间: 2019-02-25 21:50

引言

代理模式被定位为:为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。

Proxy模式根据种类不同,效果也不尽相同:

  1. 虚拟(Virtual)代理:
    根据需要创建一个资源消耗较大的对象,使得此对象只在需要时才会被真正创建。使用虚拟代理模式的好处就是代理对象可以在必要的时候才将被代理的对象加载;代理可以对加载的过程加以必要的优化。当一个模块的加载十分消耗资源的情况下,虚拟代理的好处就非常明显。
  2. 远程(Remote)代理:
    为一个位于不同的地址空间的对象提供一个局域代理对象。这个不同的地址空间可以是在本机器中,也可以是另一台机器中。远程代理又叫做大使(Ambassador)。好处是系统可以将网络的细节隐藏起来,使得客户端不必考虑网络的存在。客户完全而可以认为被代理的对象是局域的而不是远程的,而代理对象承担了大部分的网络通讯工作。由于客户可能没有意识到会启动一个耗费时间的远程调用,因此客户没有必要的思想准备。
  3. 智能引用(SmartReference)代理:
    当一个对象被引用时,提供一些额外的操作,比如将对此对象调用的次数记录下来等。
  4. Copy-on-Write代理:
    虚拟代理的一种。把复制(克隆)拖延到只有客户端需要时,才真正采取行动。
  5. 保护(Protector Access)代理:
    控制对一个对象的访问,如果需要,可以给不同的用户提供不同级别的使用权限。保护代理的好处是他可以在运行时对用户的有关权限进行检查,然后在核实后决定将调用传递给被代理的对象。
  6. Cache代理:
    为摸一个目标操作的结果提供临时的存储空间,以便多个客户端可以共享这些结果。
  7. 防火墙(Firewall)代理
    保护目标,不让恶意用户接近。
  8. 同步化(Synchronization)代理:
    使几个用户能够同时使用一个对象而没有冲突。

在所有种类的代理模式中,虚拟(Virtual)代理、远程(Remote)代理、智能引用代理(SmartReference Proxy)和保护(Protector Access)代理是最为常见的代理模式。

虚拟代理实现

考虑一个可以在文档中嵌入图形对象的文档编辑器。有些图形对象的创建开销很大。但是打开文档必须很迅速,因此我们在打开文档时应避免一次性创建所有开销很大的对象。这里就可以运用代理模式,在打开文档时,并不打开图形对象,而是打开图形对象的代理以替代真实的图形。待到真正需要打开图形时,仍由代理负责打开。这是[DP]一书上的给的例子。

// 抽象类
class Image
{
public :
    Image(std::string name) : m_name(name){ }
    virtual ~Image( ){ }

    virtual void Show( ) = 0;           // 显示文档的函数 

protected :
    std::string m_name;             // 文档名
};

// 大型实体类 
class BigImage : public Image
{
public :
    BigImage(std::string name) : Image(name){  }
    virtual ~BigImage( ){  }

    void Show( )
    {
        std::cout <<"This is Big Image..." <<std::endl;
    }
};

// 大型图片代理器 
class BigImageProxy : public Image
{
public :
    BigImageProxy(std::string name) :Image(name), m_bigImage(NULL){ }
    virtual ~BigImageProxy( )
    {
        delete m_bigImage;
    }

    void Show( )
    {
        if(this->m_bigImage == NULL)
        {
            m_bigImage = new BigImage(this->m_name);
        }
        m_bigImage->Show( );
    }

private :
    BigImage *m_bigImage;
};

客户端调用的代码就成为

// 客户端代码 
int main( )
{
    Image *Image = new BigImageProxy("Image.txt");
    Image->Show( );
    delete Image;

    return 0;
}

转载自:https://blog.csdn.net/gatieme/article/details/18035751

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!

发表评论

电子邮件地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据