设计模式——代理模式

2023-08-19  本文已影响0人  东方胖

Provide a surrogate or placeholder for annother obeject to control access to it.

代理模式的结构有益于几乎所有的构建类设计模式。
它的 UML 图类似一个三角形

proxy uml 图,使用staruml 绘制
class Grapic
{
public:
    virtual void draw() = 0;
    virtual void save() = 0;
    virtual void load() = 0;
};


class Image: public Grapic
{
public:
    void draw() {
        std::cout << "draw a image self" << std::endl; 
    }

    void save() {
       std::cout << "save on disk" << std::endl;
    }

    void load() {
         std::cout << "load from disk .." << std::endl;
    }

};

class ImageProxy: public Grapic
{
public:
    ImageProxy(const char *imageFile, Context* context) {
        _imageFile = imageFile;
        _image = nullptr;
    }
    void draw() {
          _image->draw();
    }
   void load() {
        if (_context->getUser() == UserRole::Super)
            return _image->load();
       std::cout << "have not access right" << std::endl;
      return;
  }

protected:
   Image* loadImage() {
    if (_image == nullptr) {
         return new Image();
    }
    return _image;
  }
private:
    char * imageFile;
    Image *_image;
};

代理模式有两个典型的特征:

因为有第二条,所有代理总是可以通过这个引用操纵真实的对象。

乍看十分别扭的结构,它会在什么场景下有用呢?
因为 ImageProxy 几乎就是 Image的影子,但是它们只是在抽象接口上是一致的,彼此的 constructor 和 属性其实可以大不一样,Proxy可以控制对 被代理对象的访问——做到这一点,只需要在代码中,凡出现要传递 被代理对象的上层client代码中,代之以 Proxy 。

比方说,上面的 Image 的 load 动作,它是一个抽象的接口,
当从代理的 load 入口走进去的时候,先从上下文中获取一些类似角色的参数,校验其访问权限是否满足

这是一种类似权限控制的访问场景。因为 new Image() 的动作完全被代理负责。

void operate(Graphic* g); 

那么可以可以用代理调用

operate(new ImageProxy()) ; // C++ 注意持有 代理的指针进行内存管理

智能指针 是 C++为了实现内存自动管理的一种技术——将原始的指针封装在一个有构造函数和析构函数的类中,利用栈对象自动调用析构的特性实现自动化释放内存。

在std::auto_ptr 里可能不太能清晰地看到代理模式的三角结构。但是如果我们把运算符 -> * 看成是一个公共接口的话,auto_ptr 和 裸指针对象都支持该运算,因而可以视为一种公共的接口,这样看来,它们完全符合代理模式的三角接口。

试用伪代码表达如下, -> 用接口 reference 表示,deReference代替 * 运算
于是有一个“看不见”的公共接口,大概定义成这样

template<class T>
class PointerInterface
{
public:
    T* reference() = 0;
    T deReference() = 0;
};

Pointer 具有 reference 和deReference操作。
于是智能指针 SmartPointer 也从PointerInterface 继承,然后持有Pointer 的句柄(引用) 这样,代理的三角结构是不是就很清晰了。
实际的实现中。

很关键的点也正是如此:

上一篇下一篇

猜你喜欢

热点阅读