博主按:《每天一个设计模式》旨在初步领会设计模式的精髓,目前采用
javascript
(靠这吃饭)和python
(纯粹喜欢)两种语言实现。固然,每种设计模式都有多种实现方式,但此小册只记录最直截了当的实现方式 :)
代理商模式的定义:为一个对象提供一种代理商以方便对它的访问。
代理商模式可以处理避免对少量对象的直接访问,以此为基础,常见的有保护代理商和虚拟代理商。保护代理商可以在代理商中直接拒绝对对象的访问;虚拟代理商可以推迟访问到真正需要的时候,以节省程序开销。
代理商模式有高度解耦、对象保护、易修改等优点。
同样地,由于是通过“代理商”访问对象,因而开销会更大,时间也会更慢。
class Image: def __init__(self, filename): self.filename = filename def load_img(self): print("finish load " + self.filename) def display(self): print("display " + self.filename)# 借助继承来实现代理商模式class ImageProxy(Image): def __init__(self, filename): super().__init__(filename) self.loaded = False def load_img(self): if self.loaded == False: super().load_img() self.loaded = True def display(self): return super().display()if __name__ == "__main__": proxyImg = ImageProxy("./js/image.png") # 只加载一次,其它均被代理商阻拦 # 达到节省资源的目的 for i in range(0,10): proxyImg.load_img() proxyImg.display()
main.js
:
// main.jsconst myImg = { setSrc(imgNode, src) { imgNode.src = src; }};// 利用代理商模式实现图片懒加载const proxyImg = { setSrc(imgNode, src) { myImg.setSrc(imgNode, "./image.png"); // NO1. 加载占位图片并且将图片放入<img>元素 let img = new Image(); img.onload = () => { myImg.setSrc(imgNode, src); // NO3. 完成加载后, 升级 <img> 元素中的图片 }; img.src = src; // NO2. 加载真正需要的图片 }};let imgNode = document.createElement("img"), imgSrc = "https://pic.songma.com/wenzhang/20181126/khh44ufucj0137.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1000/format/webp";document.body.appendChild(imgNode);proxyImg.setSrc(imgNode, imgSrc);
main.html
:
<!-- main.html --><!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>每天一个设计模式 · 代理商模式</title></head><body> <script src="./main.js"></script></body></html>