自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

如何用狀態(tài)模式優(yōu)化你的 JavaScript 代碼

開發(fā) 前端
狀態(tài)模式是一個有趣的模式,它可能是解決一些需求場景的最佳方式。雖然狀態(tài)模式不是一種易于學(xué)習(xí)的模式(它通常會導(dǎo)致代碼量增加),但一旦您了解了狀態(tài)模式的本質(zhì),您將在未來感謝它無與倫比的好處。

狀態(tài)模式是一個有趣的模式,它可能是解決一些需求場景的最佳方式。雖然狀態(tài)模式不是一種易于學(xué)習(xí)的模式(它通常會導(dǎo)致代碼量增加),但一旦您了解了狀態(tài)模式的本質(zhì),您將在未來感謝它無與倫比的好處。

網(wǎng)上很多文章在解釋狀態(tài)模式時,都過于理論化,難以理解。這里我嘗試用一個實(shí)際案例用通俗易懂的方式來解釋。

01、打開/關(guān)閉燈?

圖片

讓我們想象一個場景,其中有一盞燈只有一個開關(guān)。

  • 燈亮?xí)r按下開關(guān),燈將關(guān)閉。
  • 再按一下開關(guān),燈就亮了。

圖片

我們可以發(fā)現(xiàn)一個特點(diǎn):同一個開關(guān)按鈕在不同的狀態(tài)下會有不同的行為。

現(xiàn)在讓我們編寫一段代碼來模擬燈光,并打開和關(guān)閉燈光,如何編寫代碼?

一個簡單的實(shí)現(xiàn):

class Light{
constructor() {
this.state = 'off'
}


clickButton() {
if (this.state === 'off') {
console.log('turn on the light')
this.state = 'on'
} else if (this.state === 'on') {
console.log('turn off the light')
this.state = 'off'
}
}
}

圖片

用法:

圖片

02、多態(tài)

在上面的場景中,燈只有兩種狀態(tài),所以代碼寫起來比較簡單。

但我們需要知道,在現(xiàn)實(shí)生活中,很多物體都有兩種以上的狀態(tài),一旦一個對象有更多的狀態(tài),它就會更麻煩。

例如,有些手電筒具有三種狀態(tài):

  • 關(guān)閉狀態(tài)
  • 弱光狀態(tài)
  • 強(qiáng)光狀態(tài)?

第一次按下開關(guān)打開弱光,第二次按下打開強(qiáng)光,第三次按下關(guān)閉燈。

圖片

現(xiàn)在讓我們模擬這樣的行為,我們應(yīng)該如何寫代碼?

03、正常解決方案

正常的解決方案是擴(kuò)展前面的代碼,在clickButton方法中進(jìn)行一些額外的狀態(tài)判斷和狀態(tài)切換。

class Light{
constructor() {
this.state = 'off'
}


clickButton() {
if (this.state === 'off') {
console.log('Turn on the low light')
this.state = 'lowLight'
} else if (this.state === 'lowLight') {
console.log('Switch to the strong light')
this.state = 'strongLight'
} else if (this.state === 'strongLight') {
console.log('turn off the light')
this.state = 'off'
}
}
}


圖片


雖然這樣的代碼可以滿足要求,但它有很多缺點(diǎn)。

  • 如果以后需要添加或者修改Light的狀態(tài),那么就需要不斷的修改clickButton方法,使得clickButton不穩(wěn)定,不符合開閉原則。
  • 同時,所有與狀態(tài)相關(guān)的行為都放在了clickButton方法中,不符合單一職責(zé)原則。如果以后加入新的狀態(tài),比如superStrongLight,clickButton方法會越來越臃腫。
  • 最后,狀態(tài)之間的切換完全依賴于在 clickButton 方法中堆疊 if 和 else 語句。添加或修改狀態(tài)可能需要更改多個操作,這使得該方法更難以閱讀和維護(hù)。

圖片

04、分析

讓我們回想一下,我們的代碼使用 Light 作為一個單獨(dú)的對象,然后它具有三種狀態(tài)。然后我們需要讓它在不同的狀態(tài)之間切換,我們將不同的狀態(tài)視為光的內(nèi)部屬性。

但實(shí)際上,我們可以打破慣性思維,將每一個狀態(tài)都視為一個獨(dú)立的存在,封裝成一個單獨(dú)的類。

比如這里的燈有三種狀態(tài):

  • 低光狀態(tài)
  • 強(qiáng)光狀態(tài)
  • 關(guān)閉狀態(tài)

不同狀態(tài)的燈有自己的行為特征。

LowLightState 的clickButton 方法將狀態(tài)切換為StrongLightState,StrongLightState 的clickButton 將狀態(tài)切換為OffState。

圖片

而我們的Light只需要關(guān)注它處于什么狀態(tài),不需要處理狀態(tài)切換,狀態(tài)切換由每個狀態(tài)自己處理。

這是完整的代碼:

class OffLightState{
constructor(light) {
this.light = light
}


clickButton() {
console.log('Turn on the low light')
this.light.setState(this.light.lowLightState)
}
}


class LowLightState {
constructor(light) {
this.light = light
}


clickButton() {
console.log('Switch to the strong light')
this.light.setState(this.light.strongLightState)
}
}


class StrongLightState {
constructor(light) {
this.light = light
}


clickButton() {
console.log('turn off the light')
this.light.setState(this.light.offLightState)
}
}




class Light{
constructor() {
this.offLightState = new OffLightState(this);
this.lowLightState = new LowLightState(this);
this.strongLightState = new StrongLightState(this);
this.currentState = this.offLightState
}


setState(newState) {
this.currentState = newState
}


clickButton() {
this.currentState.clickButton()
}
}


let light = new Light()


light.clickButton()
light.clickButton()
light.clickButton()

圖中解釋:

圖片

這樣的代碼可以解決前面提到的問題:

輕物體更簡單。它只需要調(diào)用this.currentState.clickButton(),狀態(tài)切換可以由狀態(tài)對象自己處理。

如果將來有新的狀態(tài),我們只需要創(chuàng)建一個新的狀態(tài)類,然后修改其相鄰的狀態(tài)類,而不需要對現(xiàn)有代碼進(jìn)行大量修改。

圖片

這種編寫代碼的技術(shù)就是狀態(tài)模式。

05、狀態(tài)模式

狀態(tài)模式的正式定義:

狀態(tài)模式是一種行為軟件設(shè)計模式,它允許對象在其內(nèi)部狀態(tài)發(fā)生變化時改變其行為。這種模式接近于有限狀態(tài)機(jī)的概念。狀態(tài)模式可以解釋為策略模式,它能夠通過調(diào)用模式接口中定義的方法來切換策略。?

簡單來說,如果你的對象有多個狀態(tài),并且不同狀態(tài)的對象表現(xiàn)不同,那么你可以考慮使用狀態(tài)模式。

狀態(tài)模式有時會增加代碼行數(shù),但代碼的質(zhì)量并不取決于代碼行數(shù)。使用狀態(tài)模式通??梢允鼓膶ο蟮倪壿嫺雍啙?。

總結(jié)

以上就是我今天與你分享的關(guān)于在JavaScript中使用狀態(tài)模式簡化對象的全部內(nèi)容,希望這些內(nèi)容對你有幫助,如果你覺得我今天的內(nèi)容有用的話,請將它分享給你身邊的朋友,也許能夠幫助到他。

責(zé)任編輯:華軒 來源: 前端之窗
相關(guān)推薦

2012-06-18 15:18:32

JS

2022-06-20 08:16:42

享元模式優(yōu)化系統(tǒng)內(nèi)存

2011-07-13 09:46:23

javaScript

2021-06-05 05:11:52

代碼狀態(tài)機(jī)邏輯

2023-10-26 07:15:46

2012-03-12 09:33:04

JavaScript

2024-09-14 11:23:19

2022-08-31 12:15:09

JavaScript代碼優(yōu)化

2019-07-09 10:51:53

HTTPS優(yōu)化服務(wù)器

2018-12-04 08:00:00

網(wǎng)絡(luò)測量PerfSONAR網(wǎng)絡(luò)性能

2021-12-09 10:24:47

Javascript 高階函數(shù)前端

2009-06-22 11:52:00

javascriptxml

2021-04-27 06:44:03

PythonCython編程語言

2022-05-20 08:09:18

設(shè)計模式后端代碼

2009-06-10 22:00:57

JavaScript腳

2009-06-11 17:15:23

JavaScript性

2021-11-29 08:50:57

Javascript存儲函數(shù)

2017-10-27 22:03:35

javascrip

2011-03-01 16:08:46

2022-09-03 15:03:36

AndroidGerrit代碼審核
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號