一佩研、代碼與設(shè)計模式
1.1. 我們寫代碼到底是在寫什么零聚?
大家可以把自己的項目或者是代碼理解成我們就是在編寫模塊,并且設(shè)計它們之間的溝通。其實一個項目或者功能我們都可以理解成它們就是通過模塊和模塊之間的互相溝通來完成的趁猴。所以說設(shè)計模式余指,說白了就是在幫助我們更好的去設(shè)計模塊,并且更好的組織它們之間的溝通垢粮。
1.2. 設(shè)計模式在代碼中扮演的角色是什么?
- 幫助我們更好的組織模塊:通過一些設(shè)計模式耀鸦,組織模塊間的組成結(jié)構(gòu)和模塊劃分
- 幫助我們更好的設(shè)計溝通:有的設(shè)計模式它的目的就是來幫助我們設(shè)計模塊間如何溝通
- 提高代碼質(zhì)量:通過設(shè)計模式嗅虏,讓自己的代碼看起來更加優(yōu)雅,拋棄那些繁雜而無用的代碼
1.3. 代碼的設(shè)計原則是什么?
在開始學(xué)習(xí)設(shè)計模式之前我們非常有必要先來認(rèn)識一下設(shè)計原則,因為設(shè)計模式其實可以看做是設(shè)計原則的一個具體體現(xiàn)紧武。
設(shè)計原則如下圖所示:
- 開閉原則:開閉原則就是說我們的程序要對擴展開放番舆,對修改關(guān)閉禾怠。我們的程序要留出給具體使用的時候擴展功能的接口芽偏,但是在具體使用的時候不能讓它去修改我們的源碼,也就是說讓我們在具體的使用我們框架或程序的時候弦讽,我們能夠不用修改源碼來擴展功能往产,像jQuery、vue畏鼓、react它們都留出了很多擴展接口,平常說的vue插件堆缘,webpack插件都可以看成是一個開閉原則的體現(xiàn)滔灶。所以說我們平常在設(shè)計程序的時候,要留出一個給具體使用時擴展的接口缀皱,但是我們要封裝自己的代碼斗这,不能讓外部去修改。
- 單一職責(zé)原則:單一職責(zé)原則對我們設(shè)計程序非常有指導(dǎo)意義啤斗,它的意思就是說我們的一個模塊只做一件事情表箭,模塊的工作越單一越好。
- 依賴倒置原則:依賴倒置原則的核心思想是上層模塊不要依賴于具體的下層模塊钮莲,而應(yīng)該依賴于抽象免钻,例如:我們的食物有很多種彼水,但我們往往會選擇餐廳作為我們吃東西的依賴,而不是選擇具體的食物來作為吃東西的依賴极舔。舉例:
假設(shè)我們有四種食物凤覆,分別是food1、food2拆魏、food3盯桦、food4廷区,然后在點餐的時候我們有一個order類鳍侣,我們可以通過order這個類點餐党巾,現(xiàn)在的問題在于order這個類它要具體依賴于食物還是依賴于什么?
先看反面演示溪掀,如果把order類(點餐)直接依賴于具體的食物,那么對于不同的食物我們就要設(shè)置不同的點餐方法(orderFood1步鉴、orderFood2揪胃、orderFood3...),如果有四種食物我們就需要在order類的prototype上面放上四個方法氛琢,如果食物很多就要寫很多點餐方法喊递,顯然這樣會產(chǎn)生很多問題。比如我們依賴具體的食物阳似,一旦我們具體的食物發(fā)生了變動骚勘,對應(yīng)的點餐方法也要發(fā)生變動,新增了食物或減少了食物點餐的方法也要去新增或減少撮奏。
要保證具體所使用的上層接口不會被下層接口的劇烈變動影響到俏讹,通常的做法就是在上層和下層之間加一層抽象層,所以我們可以不要讓它依賴具體的食物畜吊,而是抽象出一個餐館層泽疆,然后讓我們的點餐類只依賴于這個抽象餐館層而不是依賴于具體的某一個食物。
這個時候玲献,為了避免下層這些具體的食物的變動會影響到具體點餐時點餐方法的變動殉疼,我們新增一個resturn函數(shù)作為中間層也就是餐館層,餐館層接收對應(yīng)的食物名捌年,然后新建一個list作為菜單瓢娜,根據(jù)接收到的食物名返回對應(yīng)的食物出去。
此時上層的點餐接口也就是order可以改變一下礼预,接收食物名然后返回餐館層對應(yīng)的食物
這樣下層的食物層無論怎么變動都不會影響到具體使用的order層恋腕,只需要去改變抽象層也就是餐館層就可以了,這就是依賴倒置原則逆瑞。
- 接口隔離原則:接口應(yīng)該細(xì)化荠藤,功能應(yīng)該單一伙单,不要一個接口調(diào)用太多的方法,而是應(yīng)該盡量的細(xì)化接口使其能力單一哈肖。它有點像單一職責(zé)原則吻育,但它們的關(guān)注點不同,單一職責(zé)原則主要關(guān)注于模塊本身淤井,接口隔離原則主要關(guān)注于接口
- 迪米特法則:迪米特法則也叫最少知識原則布疼,它的意義是如果我們讓兩個對象產(chǎn)生溝通,那么最好是讓兩個對象之間互相了解的越少越好币狠,對象之間要產(chǎn)生溝通沒有必要彼此非常了解游两。這個思想在設(shè)計模式有個比較典型的體現(xiàn)就是中介者模式,中介者模式就是讓兩個對象之間不直接溝通漩绵,通過中介者轉(zhuǎn)達(dá)需求贱案。
- 里氏替換原則:里氏替換原則主要關(guān)注于繼承,它的意義是我們?nèi)魏胃割愂褂玫牡胤街雇拢伎梢允褂米宇惾ヌ鎿Q宝踪,說白了就是子類去繼承父類的時候,子類必須保證完全繼承父類的任何屬性和方法碍扔,這樣父類使用的地方能夠使用子類進(jìn)行替換瘩燥。
以上六大設(shè)計原則是我們開發(fā)時的指導(dǎo)思想,設(shè)計模式是設(shè)計原則的具體體現(xiàn)不同,在學(xué)習(xí)設(shè)計模式的時候就可以體會到這一點厉膀。
二、設(shè)計模式的分類
我們的各種設(shè)計模式可以分為四大類
- 創(chuàng)建型:設(shè)計模式大家可以看成就是幫助和指導(dǎo)我們怎么去創(chuàng)建對象二拐、怎么去創(chuàng)建模塊以及怎么去設(shè)計模塊之間的溝通站蝠,創(chuàng)建型的目的就是幫助我們更優(yōu)雅的創(chuàng)建對象
- 結(jié)構(gòu)型:幫助我們更優(yōu)雅的設(shè)計整體以及局部的代碼結(jié)構(gòu)
- 行為型:它是模塊間的行為模式總結(jié),目的是幫助我們組織模塊的行為卓鹿,組織它們之間怎么互相溝通來達(dá)成功能目標(biāo)
- 技巧型:幫助我們優(yōu)化代碼
2.1. 創(chuàng)建型設(shè)計模式
- 工廠模式-大量創(chuàng)建對象:工廠模式相當(dāng)于建造一個創(chuàng)建對象的工廠菱魔,然后告訴工廠我們需要什么對象,工廠就把對象返回給我們吟孙,工廠模式適用于大量創(chuàng)建對象的場景澜倦。
- 單例模式-全局只能有我一個:單例模式意思是我們需要如何設(shè)計代碼,保證全局某一個特定的實例化對象只能有一個杰妓。
- 建造者模式-精細(xì)化組合對象:建造者模式適用于創(chuàng)建一個復(fù)雜的對象藻治,其實就是精細(xì)化組合一個對象。
- 原型模式-JavaScript的靈魂:原型模式相當(dāng)于原型鏈巷挥,它的意義是通過定義原型桩卵,后面創(chuàng)建的對象都依賴這個原型。(也叫委托模式,是將屬性和方法等行為委托給父級來實現(xiàn)的設(shè)計模式)
通過以上四個設(shè)計模式可以看出創(chuàng)建型設(shè)計模式都是指導(dǎo)我們?nèi)绾稳?chuàng)建對象雏节。
2.2. 結(jié)構(gòu)型設(shè)計模式
- 外觀模式-給你一個套餐:外觀模式就像我們?nèi)ゲ蛷d點一個套餐胜嗓,我們不用關(guān)心具體要求點什么菜,只需要點具體的套餐就行了钩乍,對于代碼就是說我們把接口細(xì)化之后可以給調(diào)用者一個套餐辞州,而不是讓他關(guān)心具體應(yīng)該使用哪一個接口。
- 享元模式-共享來減少數(shù)量:享元模式的目的主要是為了減少對象或者代碼塊的數(shù)量寥粹,當(dāng)存在大量重復(fù)的對象或代碼塊時变过,可以觀察一下這些對象和代碼塊之間有哪些不同的地方,然后把不同的地方提取為一個公共的享元涝涤,通過這個公共的享元來減少對象或代碼塊的數(shù)量媚狰。
- 適配器模式-用適配代替更改:當(dāng)存在兩個對象之間接口、數(shù)據(jù)不適配的時候阔拳,我們不用去更改這兩個對象崭孤,而是通過寫一段適配代碼把接口或者數(shù)據(jù)進(jìn)行適配。
- 橋接模式-獨立出來衫生,然后再對接過去:橋接模式關(guān)注于減少代碼的耦合度裳瘪,它的做法是將代碼中的一些東西獨立出來土浸,然后再組合回去罪针,來減少代碼之間的耦合度。
- 裝飾者模式-更優(yōu)雅的擴展需求:裝飾者模式主要應(yīng)對于當(dāng)我們的方法不滿足現(xiàn)在的需求時如何更優(yōu)雅的去擴展這個方法黄伊。
通過以上五個設(shè)計模式可以看出結(jié)構(gòu)型設(shè)計模式是幫助我們更優(yōu)雅的設(shè)計整體以及局部的代碼結(jié)構(gòu)泪酱。
2.3. 行為型設(shè)計模式
- 觀察者模式-我作為第三方轉(zhuǎn)發(fā):觀察者模式相當(dāng)于定義一個第三方,模塊間的溝通通過這個第三方來進(jìn)行轉(zhuǎn)發(fā)还最。
- 職責(zé)鏈模式-像生產(chǎn)線一樣組織模塊:職責(zé)鏈模式相當(dāng)于把各個模塊之間組織成一條生產(chǎn)線墓阀,這個模塊完成了就把任務(wù)交到下一個模塊繼續(xù)包裝,依次傳遞拓轻。
- 狀態(tài)模式-用狀態(tài)代替判斷:狀態(tài)模式主張用狀態(tài)代替判斷斯撮,可以非常有效的減少if else分支,能夠讓對象根據(jù)不同的狀態(tài)來展現(xiàn)不同的行為扶叉。
- 命令模式-用命令去解耦:命令模式指導(dǎo)我們用命令去解除執(zhí)行者與命令者之間的耦合勿锅,我們無需關(guān)心執(zhí)行者具體是誰、他要做什么枣氧,我們只需要給執(zhí)行者一道命令執(zhí)行者就會去執(zhí)行溢十。
- 策略模式-算法工廠:策略模式和狀態(tài)模式有點類似,但是策略模式可以理解為一個算法工廠达吞,告訴它要什么算法张弛,它就返回什么算法。
- 迭代器模式-告別for循環(huán):迭代器模式就是我們在不去了解某一個對象內(nèi)部的情況下能夠有序的去遍歷這個對象內(nèi)部,例如ES6的forEach循環(huán)吞鸭。
通過以上六個設(shè)計模式可以看出行為型設(shè)計模式目的是幫助我們組織模塊的行為寺董,組織它們之間怎么互相溝通來達(dá)成功能目標(biāo)。
2.4. 技巧型設(shè)計模式
- 鏈模式-鏈?zhǔn)秸{(diào)用:如jQuery的鏈?zhǔn)秸{(diào)用瞒大。
- 惰性模式-我要搞機器學(xué)習(xí):惰性模式說高大上點是搞機器學(xué)習(xí)螃征,說白點是在第一次執(zhí)行之后把執(zhí)行狀態(tài)記錄下來。
- 委托模式-讓別人代替你收快遞:委托模式相當(dāng)于收快遞透敌,把消息委托別人代收盯滚。
- 等待者模式-等你們都回來再吃飯:等待者模式適用于多種異步操作情況下,當(dāng)我們發(fā)出一堆的異步操作之后酗电,需要等待者模式幫助我們讓這些異步操作都返回了再進(jìn)行下一步操作魄藕。
- 數(shù)據(jù)訪問模式-一個方便的數(shù)據(jù)管理器:數(shù)據(jù)訪問模式就是說我們?nèi)ソ⒁粋€數(shù)據(jù)管理器。
通過以上五個設(shè)計模式可以看出技巧型設(shè)計模式目的是幫助我們更好的優(yōu)化代碼撵术。
下一篇:設(shè)計模式—關(guān)于封裝與對象學(xué)習(xí)
本文由博客一文多發(fā)平臺 OpenWrite 發(fā)布背率!