在編寫JS和組裝程式碼的過程中,運用一定的設計模式可以讓我們的程式碼更加優雅、靈活。
下面筆者就結合諸如redux的subsscribe、ES6的class、vue裡面的$dispatch、jquery裡面的on/off來給大家簡單介紹下設計模式在這些庫、語法和框架中的使用。
設計模式解決的問題
設計模式並不是很玄乎的知識,很多同學在編寫JS程式碼的時候已經在不經意間用了不少設計模式了。
筆者認為把設計模式單獨抽像出來探討,就和算法中抽像出來冒泡、排序一樣,是為了描述一種常用的JS pattern。
透過研習這類pattern,讓模式來指導我們的程式碼結構及JS演算法。
一些常用的設計模式概述
observer [觀察者模式]
根據狀態的變化主動觸發觀察者佇列、hashMap的回呼行為
🎀發布模式] 在程式碼模組的共享存取空間儲存hashMap的topic/callback形式。 添加on/off/trigger等介面實現掛載、移除、觸發等動作。 一個簡單的訂閱發布模式代碼實踐class StateTracker{ constructor(){ this.observers = []; this.internamState= 10; } // 改变内部状态,触发状态的观察者列表 change(val){ this.internamState= val; this.observers.forEach(observer=>observer(val)); } registerObserver(ObserverFn){ this.obserers.push(ObserverFn) } }singleton[單例模式] 構造函數的實例只有一個,一般是透過閉包儲存內部實例,透過介面存取內部實例。
class PubSubHandler{ constructor(){ this.eventPool = {}; } //移除 off(topicName){ delete this.observers[topicName] } //发布 trigger(topicName,...args){ this.eventPool[topicName] && this.eventPool[topicName].forEach(callback=>callback(...args)); } //订阅 on(topicName,callback){ let topic = this.eventPool[topicName] ; if(!topic){ this.eventPool[topicName] =[] } this.eventPool[topicName].push(callback) } }decorator混合模式 這個模式就是在原有的物件上面裝飾更多行為,並且保持變數名稱不變。 用過ES7的@decorator或python等語言的,應該對decorator不陌生的。
var singleton = ()=>{ var instance; var createInstance = ()=>{ this.a = 1; this.b = 2; } return { getInstance:()=>{ if(!instance){ instance = createInstance(); } return instance; } } } var test = singleton(); test.getInstance() == test.getInstance() //truemixin混合模式 這個模式和decorator有點類似,只是它的功能比較垂直。 就是在原有的物件上面增加、覆蓋物件的行為。 相較於extends、Object.assign等方法,mixin模式更有表現力。 mixin模式不能一概而論,可能依據不同的資料型別有不同的mixin策略,例如vue.mixin
function decorator(sourceObj,decortorFn){ decortorFn(sourceObj); return sourceObj } var d = {a:1}; // d变为了{a:1,b:1} d = decorator(d,(d)=>{d.b=1});筆者就暫時先介紹這麼多設計模式,以下就針對常用的框架、語法、函式庫等來說明這些設計模式的應用。 observer模式在redux中的使用
class StateTracker{ constructor(){ this.raw = { a:1, b:2 } } mixin(obj){ Object.assign(this.raw,obj) } }decorator模式在react-redux中的實踐
var store = createStore(reducer,initialState);//注册redux store,存储在 nextListeners数组 var test = store.subscribe(()=>{console.log('我注册了!')});// 取消注册监听 test.unsubscribe(); publish/subscribe在jquery中的使用 $(document).on('hello',()=>{console.log('hello')})$(document).trigger('hello');$(document).off('hello')