(五)单例模式
單例模式
- 單例模式
- 單例模式 介紹
- 概念
- 示例
- 單例模式 演示
- 單例模式 場景
- jQuery 只有一個(gè) `$`
- 登錄
- 其他
- 單例模式 總結(jié)
單例模式
- 介紹
- 演示
- 場景
- 總結(jié)
單例模式 介紹
- 系統(tǒng)中被唯一使用
- 一個(gè)類只有一個(gè)實(shí)例
概念
單例模式,是一種常用的軟件設(shè)計(jì)模式。在它的核心結(jié)構(gòu)中只包含一個(gè)被稱為單例的特殊類。通過單例模式可以保證系統(tǒng)中,應(yīng)用該模式的類一個(gè)類只有一個(gè)實(shí)例。即一個(gè)類只有一個(gè)對象實(shí)例
示例
按照面向?qū)ο蟮木幊趟枷?#xff0c;任何東西都可以抽象為一個(gè)類,然后可以 new 出若干個(gè)對象。但是針對某些場景,只能存在唯一的對象
- 系統(tǒng)登錄框
- 購物車
這就產(chǎn)生了和面向?qū)ο笏枷氲囊环N矛盾,而單例模式就用來解決這種矛盾,讓一個(gè)類只能 new 出一個(gè)對象。
單例模式 演示
UML 類圖如下
單例模式需要用到 java 的一些特性(private)
es6 沒有這些特性(typescript除外)
因此只能用 java 進(jìn)行演示。不過沒關(guān)系,通過之前學(xué)習(xí)的知識(shí),都能看得懂。
使用代碼
public class SingletonPatternDemo {public static void main(String[] args) {//不合法的構(gòu)造函數(shù)//編譯時(shí)錯(cuò)誤:構(gòu)造函數(shù) SingleObject() 是不可見的 !!!//SingleObject object = new SingleObject();//獲取唯一可用的對象SingleObject object = SingleObject.getInstance();object.login();} }單例模式的關(guān)鍵在于不能讓外部使用者 new 出對象,即構(gòu)造函數(shù)是 private ,這一點(diǎn) JS 是無法實(shí)現(xiàn)的,非常遺憾
js通過閉包實(shí)現(xiàn)單例模式
class SingleObject {login() {console.log('login...')} } SingleObject.getInstance = (function () {let instancereturn function () {if (!instance) {instance = new SingleObject();}return instance} })()// 測試:注意這里只能使用靜態(tài)函數(shù) getInstance ,不能 new SingleObject() !!! let obj1 = SingleObject.getInstance() obj1.login() let obj2 = SingleObject.getInstance() obj2.login() console.log(obj1 === obj2) // 兩者必須完全相等 trueconsole.log('---分割線---')let obj3 = new SingleObject() //無法完全控制 obj3.login() console.log('obj1 === obj3',obj1 === obj3) //false單例模式 場景
日常使用中,很多都用到了單例的思想,但是不一定完全按照單例的類圖來實(shí)現(xiàn):
jQuery 只有一個(gè) $
引用多次也只有一個(gè)$
// jQuery 只有一個(gè) `$` if (window.jQuery != null) {return window.jQuery } else {// 初始化... }登錄
模擬實(shí)現(xiàn)一個(gè)登錄框
class LoginForm {constructor() {this.state = 'hide'}show() {if (this.state === 'show') {alert('已經(jīng)顯示')return}this.state = 'show'console.log('登錄框已顯示')}hide() {if (this.state === 'hide') {alert('已經(jīng)隱藏')return}this.state = 'hide'console.log('登錄框已隱藏')} } LoginForm.getInstance = (function () {let instancereturn function () {if (!instance) {instance = new LoginForm();}return instance} })()// 一個(gè)頁面中調(diào)用登錄框 let login1 = LoginForm.getInstance() login1.show() // login1.hide()// 另一個(gè)頁面中調(diào)用登錄框 let login2 = loginForm.getInstance() login2.show()// 兩者是否相等 console.log('login1 === login2', login1 === login2) //true其他
- 購物車,和登錄框?qū)崿F(xiàn)方式差不多
- redux 和 vuex 的 store
單例模式 總結(jié)
- 什么是單例模式
- java 實(shí)現(xiàn)單例模式的核心(private 構(gòu)造函數(shù))
- js 實(shí)現(xiàn)單例模式
- 使用單例模式的場景
單例模式 vs 單一職責(zé)原則
- 單一職責(zé)原則是針對所有的設(shè)計(jì),單個(gè)功能盡量拆分,一個(gè)模塊做好一個(gè)功能。如果做不好,會(huì)帶來模塊臃腫,不好維護(hù)。
- 單例模式是系統(tǒng)的只能有一份唯一的數(shù)據(jù),如果不這樣做,會(huì)出 bug 的
設(shè)計(jì)原則驗(yàn)證:
- 符合單一職責(zé)原則,只實(shí)例化唯一的對象
- 沒法具體開放封閉原則,但是絕對不違反開放封閉原則
總結(jié)