惰性單例模式
之前介紹了JS中類的單例模式,這次我們討論下單例模式的應用。在眾多網站中,登錄框的實現方式就是一個單例,點擊一次就展示一次,所以我們可以在頁面加載好的時候就創建一個登錄框,點擊頁面上的登錄按鈕時,用於控制它的顯示和隱藏。
代碼實現:
這樣的問題就是,如果用戶進來后所有的操作根本沒有用到登錄,那創建登錄框這個操作就是無用的,所以改進為當用戶點擊登錄按鈕時才開始創建登錄框,如下:
現在達到了惰性的目的,但失去了單例的效果。每次點擊登錄都會創建一個登錄框,所以還要加個變量控制這個框唯一顯示:
這里使用了閉包,將控制變量放到閉包里,防止全局污染,當第一次點擊時,創建並顯示登錄框,再次點擊后,不再進行創建直接顯示。
這樣就實現了這個登錄框的惰性單例模式,但是他存在以下問題:
- 仍然違反了單一職責原則,管理單例和創建對象的代碼放在了同一函數內部。
- 如果以后我想創建一個單例的表格,一個單例的iFrame,還要每次都這樣重復寫一遍,如法炮制
所以有沒有一種通用的方法抽象這種模式呢?
通用的單例模式
先不考慮創建的東西是什么,我們先把管理單例的代碼抽象出來,創建對象的方法當做此單例函數的參數傳入:
我們創建了一個通用的單例函數,只專注與單例相關的代碼,接受一個fn參數,將fn的執行結果存到result中,result由於在函數閉包里,所以不會被銷毀。將來使用時result如果是已賦值的,那么直接返回這個單例值,這樣如果需要創建一個單例的iFrame,只需要寫一個代碼邏輯與createLoginDiv差不多的createiFrame,放到getSingle里返回即可使用。
通過結合前一篇[JavaScript設計模式] 什么是單例模式的學習,我們了解了單例模式,尤其以惰性單例模式這種概念,在需要的時候才去創建對象,而且是唯一的對象。還有單一職責原則,創建對象和管理單例被放在兩個不同的方法中,組合起來以達到我們想要的目的。