設計模式的概念

語言: CN / TW / HK

這是我參與「第四屆青訓營」筆記創作活動的的第8天

設計模式的概念

設計模式就是前輩們程式碼設計的一個總結,也就是寫程式碼的最佳實踐,讓程式碼有更好的可複用性、可讀性、可維護性,設計模式的本質是面向物件設計原則的實際運用,是對類的封裝性、繼承性和多型性以及類的關聯關係和組合關係的充分理解。目前為止共有23種設計模式,但是有些設計模式不太常用。

7大設計原則

1.單一職責原則 SRP

我們設計的類儘量負責一項功能,如A類只負責功能A,B類只負責功能B,不要讓A類既負責功能A,又負責功能B,這樣會導致程式碼混亂,容易產生bug。

2.開放-封閉原則 OCP

是程式設計彙總最基礎,最重要的設計原則,核心為對擴充套件開發,對修改關閉,簡單來說,通過擴充套件軟體的行為來實現變化,而不是通過修改來實現,儘量不修改程式碼,而是擴充套件程式碼。

3.里氏替換原則 LSP

程式中的子類應該可以替換父類出現的任何地方並保持預期不變。所以子類儘量不要改變父類方法的預期行為。

4.介面隔離原則 ISP

類不應該依賴他不需要的介面,介面儘量小顆粒劃分。當類 A 只需要介面 B 中的部分方法時,因為實現介面需要實現其所有的方法,於是就造成了類 A 多出了部分不需要的程式碼。這時應該將 B 介面拆分,將類A需要和不需要的方法隔離開來。

5.依賴倒置原則 DIP

抽象不應該依賴細節,細節應該依賴於抽象。核心是面向介面程式設計,我們應該依賴於抽象介面,而不是具體的介面實現類或具體的物件。相對於細節的多變性,抽象的東西要穩定的多,以抽象為基礎搭建的架構比以細節為基礎的架構要穩定的多。

6.最少知識原則(迪米特原則)LOD

一個類或物件應該對其它物件保持最少的瞭解。只與直接的朋友(耦合)通訊。

7.組合/聚合複用原則 CRP

儘可能通過組合已有物件(借用他們的能力)來實現新的功能,而不是使用繼承來獲取這些能力。就是能用組合實現少用繼承。

前端常用設計模式之一--釋出訂閱模式

在很多的庫裡都能見到這個設計模式的應用,在nodejs裡對事件的監聽基本都是用EventEmitter實現的,在這裡實現一個簡單的EventEmitter。

程式碼如下:

``` class EventEmitter { constructor() { this._events = {} }

on(eventName, callback) { if (!this._events) { this._events = {} } if (this._events[eventName]) { this._events[eventName].push(callback) } else { this._events[eventName] = [callback] } } emit(eventName, ...args) { this._events[eventName].forEach((fn) => { fn(...args) }) } off(eventName, callback) { if (this._events && this._events[eventName]) { this._events[eventName] = this._events[eventName].filter( (fn) => fn !== callback && fn.a !== callback ) } }

once(eventName, callback) { const one = () => { callback() this.off(eventName, one) } one.a = callback this.on(eventName, one) } } 複製程式碼 ```

測試程式碼如下:

``` class Child extends EventEmitter { constructor() { super() } }

const child = new Child()

const happy = () => { console.log('i love you') }

const unhappy = () => { console.log('你個老六') } child.on('給你糖', happy) child.on('把你糖搶回來', unhappy)

const fn = () => { console.log('逛街') }

child.once('幹什麼', fn)

child.emit('給你糖')

console.log('________')

child.emit('把你糖搶回來')

console.log('________') setTimeout(() => { child.off('幹什麼', fn) child.emit('幹什麼') }, 1000) 複製程式碼 ```

測試結果如下圖:

image.png

「其他文章」