每天一個設計模式·代理模式

godbmw發表於2019-02-27

博主按:《每天一個設計模式》旨在初步領會設計模式的精髓,目前採用javascript靠這吃飯)和python純粹喜歡)兩種語言實現。誠然,每種設計模式都有多種實現方式,但此小冊只記錄最直截了當的實現方式 ?

0. 專案地址

1. 什麼是代理模式?

代理模式的定義:為一個物件提供一種代理以方便對它的訪問。

代理模式可以解決避免對一些物件的直接訪問,以此為基礎,常見的有保護代理和虛擬代理。保護代理可以在代理中直接拒絕對物件的訪問;虛擬代理可以延遲訪問到真正需要的時候,以節省程式開銷。

2. 代理模式優缺點

代理模式有高度解耦、物件保護、易修改等優點。

同樣地,因為是通過“代理”訪問物件,因此開銷會更大,時間也會更慢。

3. 程式碼實現

3.1 python3 實現

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()
複製程式碼

3.2 javascript 實現

main.js :

// main.js
const 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://upload-images.jianshu.io/upload_images/5486602-5cab95ba00b272bd.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>
複製程式碼

4. 參考

相關文章