设计模式 - 代理模式

142 阅读1分钟

代理模式(Proxy)

模式目的

为昂贵或者无法复制的资源提供接口。

代码示例

创建一个抽象类Image。 创建一个继承Image的RealImage类。 创建一个继承Image的ProxyImage类。

  1. Image接口
abstract class Image
{
    private $fileName;
    public function __construct($fileName)
    {
        $this->fileName = $fileName;
    }
    abstract public function display();
}
  1. 真实获取Image的类
class RealImage implements Image
{
    public function __construct($fileName)
    {
        parent::__construct($fileName);
        $this->loadFromDisk($this->fileName);
    }
    public function display()
    {
        echo "Displaying:$this->fileName";
    }
    private function loadFromDisk($fileName)
    {
        echo "Loading:$fileName";
    }
}
  1. 代理访问Image
class ProxyImage implements Image
{
    private $realImage;
    public function display()
    {
        if (is_null($this->realImage)) {
            $this->realImage = new RealImage($this->fileName);
        }
        $this->realImage->display();
    }
}
  1. 演示(Demo)
// 使用代理Image来访问图片
$proxyImage = new ProxyImage('1.jpg');
// 图像需要从磁盘加载
$proxyImage->display();
// 图像无需再次从磁盘加载
$proxyImage->display();

角色

  1. 主题(Subject) - 抽象类
  2. 真实主题(RealSubject) - 继承了Subject
  3. 代理(Proxy) - 继承了Subject

模式类型

结构型模式

JS使用代理模式实现图片懒加载

实现步骤

  1. 先展示一张占位图片(placeholder.png)
  2. 异步加载真实图片
  3. 真实图片加载完毕替换掉占位图片

代码

// 真实image
function RealImage() {
  this.imgNode = document.createElement('img')
  document.body.appendChild(this.imgNode)
}
RealImage.prototype.setSrc = function(src) {
  this.imgNode.src = src
}

// 代理image
function ProxyImage() {
  this.realImage = new RealImage()
  // 设置占位图
  this.realImage.setSrc('placeholder.png')
}
ProxyImage.prototype.setSrc = function(src) {
  const img = new Image()
  img.src = src
  img.onload = () => {
    this.realImage.setSrc(src)      
  }
}

const proxyImage = new ProxyImage()
proxyImage.setSrc('pic.png')