<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      [JS] JS單例模式的實現(xiàn)

      JS 單例模式的實現(xiàn)

      單例模式簡介

      單例模式(Singleton Pattern)是最簡單的設計模式之一。這種類型的設計模式屬于創(chuàng)建型模式,提供了一種創(chuàng)建對象的最佳方式。

      特點

      • 意圖:保證一個類僅有一個實例,并提供一個訪問它的全局訪問點。
      • 主要解決:一個全局使用的類頻繁地創(chuàng)建與銷毀。
      • 何時使用:當您想控制實例數(shù)目,節(jié)省系統(tǒng)資源的時候。
      • 如何解決:判斷系統(tǒng)是否已經(jīng)有這個單例,如果有則返回,如果沒有則創(chuàng)建。

      首先對比一下平時不使用單例模式的情況:

      在不適用單例模式的情況下,如下,會得到不同的多個實例:

      video.js

      class Video{
          constructor() {
              console.log("video created");
          }
      }
      
      export { Video };
      

      main.js

      import { Video } from "./video.js";
      
      const v1 = new Video();
      const v2 = new Video();
      
      console.log(v1 === v2);
      

      控制臺輸出

      image-20231216153428957

      方法1:提前構造實例

      提前構造一個實例,只向外部暴露該實例的引用,從而實現(xiàn)單例。

      但是缺點是需要提前構造實例,而無法做到在需要的時候創(chuàng)建實例。

      class Video{
          constructor() {
              console.log("video created");
          }
      }
      
      const v = new Video();
      
      export { v };
      

      方法2:構造方法私有化

      video.js

      class Video{
          private constructor() {
              console.log("video created");
          }
      
          static _ins = null;
          static getInstance(){
              if(!this._ins){
                  this._ins = new Video();
              }
              return this._ins;
          }
      }
      
      export { Video };
      

      main.js

      import { Video } from "./video.js";
      
      const v1 = Video.getInstance();
      const v2 = Video.getInstance();
      
      console.log(v1 === v2);
      

      通過將構造方法私有化,外部無法通過new實例化對象,只能通過靜態(tài)方法getInstance獲取實例。

      而在類的內部實現(xiàn)中,使用_ins確保只存在一個實例。

      缺點

      原生JS不存在private,需要使用TS

      JS中,如果剔除private,僅通過getInstance也可以實現(xiàn)單例模式。但是這種方法不嚴格,無法確保每一個調用者不會使用構造函數(shù)創(chuàng)建新的實例。

      方法3:通用方法——將任意類轉為單例

      singleton.js

      export function singleton(className){
          let ins;
          return class{
              constructor(...args) {
                  if(!ins){
                      ins = new className(...args);
                  }
                  return ins;
              }
          };
      }
      
      • 這個函數(shù)接收一個類,進行改造之后返回一個新的類;
      • 使用閉包,存儲實例對象ins
      • 新的類的構造函數(shù)相當于攔截作用:
        • 如果ins不存在,則將傳入的參數(shù)轉交給原來的類的構造函數(shù),并創(chuàng)建一個實例;
        • 如果ins存在,則直接返回存儲在閉包中的實例對象。

      video.js

      import { singleton } from "./singleton.js";
      
      class Video{
          constructor() {
              console.log("video created");
          }
      }
      
      const newVideo = singleton(Video);
      
      export { newVideo as Video };
      

      main.js

      import { Video } from "./video.js";
      
      const v1 = new Video();
      const v2 = new Video();
      
      console.log(v1 === v2);
      

      控制臺輸出

      image-20231216155135470

      觀察到這種實現(xiàn)下,構造函數(shù)只被調用了一次,并且v1v2指向同一個實例。

      缺點

      main.js

      Video.prototype.play = function(){
          console.log("play");
      }
      
      v1.play(); // Uncaught TypeError: v1.play is not a function
      

      在這個案例中,我們試圖在Video的原型上添加一個方法,并通過實例對象v1調用,但是v1所處的原型鏈上并不能找到這個方法。

      再回過頭來觀察singleton.js的實現(xiàn):

      export function singleton(className){
          let ins;
          return class{
              constructor(...args) {
                  if(!ins){
                      ins = new className(...args);
                  }
                  return ins;
              }
          };
      }
      
      • main.js中,我們使用的Video類來自于video.js的導出,實際上已經(jīng)是經(jīng)過singleton函數(shù)改造的類,也就是上面這段代碼中,return class {}這個匿名類。
      • 而對于v1v2,它們來自于ins這個實例對象,它由上面這段代碼的new className()創(chuàng)建,也就是說它來自于最“簡單”的、沒有經(jīng)過單例化的那個Video類。
      • 綜上,v1并不是由那個匿名類創(chuàng)建的,所以它們不在同一原型鏈上。這也是這種單例模式實現(xiàn)方式的缺點,需要改進。

      方法4:使用代理

      這個方法是對方法3的改進,使用Proxy API對類進行代理,往新的類的原型上添加方法,也會被添加到原來的類的原型上,由此解決了方法3的缺點。

      singleton.js

      export function singleton(className){
          let ins;
          return new Proxy(className, {
              construct(target, ...args){
                  if(!ins){
                      ins = new target(...args);
                  }
                  return ins;
              }
          });
      }
      

      MDN對于Proxyconstruct更詳細的介紹:handler.construct() - JavaScript | MDN (mozilla.org)

      這里的constuct主要是攔截外部的new操作,函數(shù)參數(shù)target指向代理對象,也就是這里的className,即需要被單例化的類。

      其它邏輯和方法3一致,使用閉包,通過ins存儲實例對象。

      video.js

      import { singleton } from "./singleton.js";
      
      class Video{
          constructor() {
              console.log("video created");
          }
      }
      
      const newVideo = singleton(Video);
      
      export { newVideo as Video };
      

      main.js

      import { Video } from "./video.js";
      
      const v1 = new Video();
      const v2 = new Video();
      
      console.log(v1 === v2);
      
      Video.prototype.play = function(){
          console.log("play");
      }
      
      v1.play();
      

      控制臺輸出

      image-20231216161903412

      觀察到構造函數(shù)只被調用了一次,并且在單例化的新類的原型上添加方法,實例對象v1也可以訪問到。

      這是因為newVideo是對Video的代理(這里的命名以video.js為準),在newVideo對象上的操作會被應用在Video這個對象上。

      至此,完成了JS中較為完善的單例模式實現(xiàn)。

      posted @ 2023-12-16 16:38  feixianxing  閱讀(613)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 四平市| 97精品久久久大香线焦| 白白发布视频一区二区视频| 亚洲免费一区二区av| 丰满的少妇一区二区三区| 成人无码午夜在线观看| 亚洲欧洲日韩国内高清| 国产成人综合亚洲第一区| 视频一区视频二区制服丝袜 | 99久久99这里只有免费费精品| 内射合集对白在线| 亚欧洲乱码视频一二三区| 国产性三级高清在线观看| 国产一区国产精品自拍| 中文有码字幕日本第一页| 亚洲欧美牲交| 日韩精品中文字幕无码一区| 日产日韩亚洲欧美综合下载| 日本夜爽爽一区二区三区| 五月综合激情婷婷六月| 国产精品99久久久久久www| 亚洲第一天堂无码专区| 久热这里只有精品12| 精品国产成人午夜福利| 国产一区二区三区AV在线无码观看| 久久精品国产久精国产| 麻豆精品一区二正一三区| 老司机性色福利精品视频| 久热re这里精品视频在线6| 日韩中文字幕有码av| 亚洲精品国产suv一区88| 蜜臀av黑人亚洲精品| 日本视频一两二两三区| 国产伦人人人人人人性| 免费看国产精品3a黄的视频| 亚洲 欧美 中文 日韩aⅴ| 欧美国产日韩久久mv| 四虎国产精品永久在线| 中国性欧美videofree精品| 四虎永久免费精品视频| 92国产精品午夜福利免费|