上一節(jié)主要學(xué)習(xí)創(chuàng)建型的三種設(shè)計模式是怎么使用的竹挡。如何利用創(chuàng)建型設(shè)計模式來指導(dǎo)我們更好的封裝代碼更好的創(chuàng)建對象泳赋,本節(jié)主要學(xué)習(xí)怎樣利用設(shè)計模式來提高代碼復(fù)用性弓柱。
提高可復(fù)用性的目的?
為什么要提高可復(fù)用性轮锥?提高可復(fù)用性能帶來什么好處络断?
- 遵循DRY原則:英文是dont repeat yourself尖啡,這個原則的意思是說要時刻記住去檢查你代碼之中是否有重復(fù)的代碼,如果有摧玫,把它作為一個公共部分抽象出來耳奕。
- 減少代碼量,節(jié)省開銷:遵循了DRY原則之后我們的代碼量就會減少诬像,內(nèi)存開銷也會逐漸減少屋群,因為沒有重復(fù)的代碼塊了。
什么是好的復(fù)用坏挠?
- 在對象這個層面芍躏,一個可復(fù)用性高、設(shè)計的好的代碼它的對象都是可以重復(fù)使用的癞揉,我們無須去頻繁的修改對象來讓它符合新的需求纸肉,它面向抽象而不面向具體溺欧。
- 對于進行同樣操作的代碼塊不會重復(fù)寫很多次。
- 高復(fù)用性的代碼必然是建立在一個模塊低耦合的基礎(chǔ)之上的柏肪,盡量做到模塊之間的功能單一姐刁,模塊越單一,這個模塊就能越容易被復(fù)用烦味。
一聂使、提高復(fù)用性的設(shè)計模式
1.1. 減少重復(fù)代碼數(shù)量,高效復(fù)用代碼的設(shè)計模式
橋接模式:它和DRY原則非常相似谬俄,都是把公共部分拿出來而不是耦合在現(xiàn)有的代碼當(dāng)中柏靶,通過把公共部分提取出來然后再橋接到使用的地方來減少代碼耦合。
目的:通過橋接代替耦合
應(yīng)用場景:減少模塊之間的耦合
享元模式:通過觀察相似的代碼塊和對象之間的共同點和不同點溃论,區(qū)分出公有部分和私有部分屎蜓,然后把公有部分作為一個享元抽取出來,從而減少對象或者代碼塊钥勋。
目的:減少對象/代碼數(shù)量
應(yīng)用場景:當(dāng)代碼中創(chuàng)建了大量類似對象和類似的代碼塊時就可以采用享元模式
1.2. 創(chuàng)建高可復(fù)用性代碼的設(shè)計模式
模板方法模式:定義一個操作中的算法的框架炬转,而將一些步驟延遲到子類中。使得子類可以不改變一個算法的結(jié)構(gòu)即可重定義該算法的某些特定步驟算灸。
目的:定義一系列操作的骨架扼劈,也就是說不要去具體實現(xiàn)操作,先把操作的骨架定下來菲驴,后面的類似操作就以這個骨架為基礎(chǔ)荐吵,在骨架上進行擴展和具象化來實現(xiàn)后面具體的需求,簡化后面類似操作的內(nèi)容
應(yīng)用場景:當(dāng)你在項目中出現(xiàn)了很多類似的操作赊瞬,它們可能基本的骨架是一樣的先煎,但是這些操作又具有自己的特點,這個時候我們可以使用模板方法模式
二森逮、基本結(jié)構(gòu)
2.1. 享元模式的基本結(jié)構(gòu)
需求:有一百種不同文字的彈窗榨婆,每種彈窗行為相同,但是文字和樣式不同
這種情況我們沒必要去新建一百個彈窗褒侧,我們可以創(chuàng)建一個彈窗類良风,這個彈窗類保留相同的行為,然后把顯示彈窗這個行為抽象為一個方法闷供,這個方法再接收到底要顯示什么樣的彈窗烟央;它們不同的地方是文字和樣式,所以我們可以把它們不同的地方提取出來作為數(shù)組對象進行配置歪脏,然后我們只需要創(chuàng)建一個彈窗實例疑俭,通過循環(huán)數(shù)組調(diào)用彈窗實例的顯示方法,傳入每個彈窗的文字和樣式即可婿失。代碼如下:
享元模式說白了就是當(dāng)我們觀察到對象或者代碼塊存在多個相似之處時钞艇,將它們相同的部分保留啄寡,不同的部分提取出來作為享元,這樣我們就能用一個對象來代替多個對象哩照。享元模式的核心是運用共享技術(shù)來有效支持大量細粒度的對象挺物。
2.2. 橋接模式的基本結(jié)構(gòu)
需求:有3種形狀,每種形狀都要顯示三種顏色
在這樣的情況下如果我們不去注意可復(fù)用性飘弧,很有可能就會創(chuàng)建9種不同顏色的不同形狀识藤。我們可以觀察一下:3個形狀它們可能沒有什么共同點,但是顏色有共同點次伶,所以我們可以把它們的顏色提取出來作為公用方法痴昧,這些形狀的類都依賴于這個方法,通過這個方法來展示顏色冠王,這樣我們只需要三個類即可完成需求赶撰。比如我們需要紅色的圓形,只需要new一個圓形類告訴它需要紅色即可柱彻。
橋接模式總結(jié)來說就是把這些重復(fù)的部分抽取出來作為一個公用的方法扣囊,然后再把它橋接回去,它有點類似建造者模式绒疗,先拆分然后再組合,但建造者模式的核心關(guān)注點是如何去構(gòu)建對象(關(guān)注創(chuàng)建)骂澄,而橋接模式關(guān)注的是如何通過一個橋接的方式來簡化代碼吓蘑,提高代碼可復(fù)用性(關(guān)注功能)。
2.3. 模板方法模式的基本結(jié)構(gòu)
需求:編寫導(dǎo)航組件坟冲,有的帶消息提示磨镶,有的是豎的,有的是橫的健提,后面可能還會新增其它類型
對于這種需求琳猫,我們沒必要針對每一個導(dǎo)航組件都去新建一個類,可以寫一個基礎(chǔ)的組件類私痹,具體的實現(xiàn)延遲到具體使用的時候脐嫂,代碼示例:
代碼示例中,先新建基礎(chǔ)類baseNav紊遵,在基礎(chǔ)類中定下基本骨架账千,包括它的行為也是一樣的處理,先寫出它的基礎(chǔ)行為暗膜,然后留出一個回調(diào)匀奏,等到具體決定要做消息提示型的還是其它類型的時候再通過回調(diào)來實現(xiàn)不同的地方,實現(xiàn)具體的操作和行為学搜。
三娃善、應(yīng)用示例
3.1. 享元模式的示例
3.1.1. 文件上傳
需求:項目中有一個文件上傳的功能论衍,該功能可以上傳多個文件。
先看一個沒有使用享元模式的代碼示例:
上面代碼中聚磺,在沒有使用享元模式的情況下坯台,我們要上傳四個文件,就需要new四個uploader類分別指定文件咧最,如果我們使用享元模式優(yōu)化這段代碼:
- 提取公有部分和私有部分:我們觀察一下捂人,對于這四個對象而言,它們的私有部分是要上傳的文件和文件類型是不同的矢沿,而公有部分是每個對象都具有初始化滥搭、刪除、上傳的功能方法捣鲸,享元模式就是把這四個對象的私有部分作為公共的享元提取出來瑟匆,所以我們寫一個數(shù)組,將這幾個對象的私有部分儲存起來
然后將公有部分都保留下來栽惶,所以說上面prototype上的init方法愁溜、delete方法、uploading方法都可以抄下來保留外厂,而uploader類中的屬性就可以刪掉不需要了冕象,我們把上傳的文件、文件類型都作為參數(shù)傳入uploading方法中
這么一改造之后汁蝶,我們只需要實例化一次uploader渐扮,然后循環(huán)數(shù)組調(diào)用實例對象的uploading方法,傳入文件和文件類型即可掖棉。
再次總結(jié)享元模式:享元模式到底怎么用墓律?其實就是去觀察代碼中重復(fù)的部分,去看一下它們有哪些部分是私有的幔亥,哪些部分是公有的耻讽,然后把私有的部分提取出來作為公用的享元,享元的形式不一定非要是數(shù)組帕棉,它可以是對象也可以是方法等等针肥。這種思想就像我們生活中一個很簡單的道理,我們要試穿一百套衣服笤昨,沒必要去請一百個模特祖驱,我們可以請一個模特分別試穿這一百套衣服。
3.1.2. jQuery中的extend
需求:extend方法瞒窒,需要判斷參數(shù)數(shù)量來進行不同的操作捺僻。
jQuery的extend方法如果給它一個參數(shù),比如給個對象,就會把這個對象擴展到j(luò)Query上面去匕坯,如果給它兩個對象束昵,它會將這兩個對象合并之后返回出來,例如:
對于這樣的操作葛峻,我們可能會想到先寫一個extend方法锹雏,然后在方法內(nèi)部通過argument對象去判斷參數(shù)的數(shù)量,根據(jù)argument不同的長度去進行不同的操作术奖,如:
這樣的代碼從原則上來說沒有錯誤礁遵,但是可以發(fā)現(xiàn)這兩段for in循環(huán)是極其相似的,DRY原則告訴我們要盡量減少重復(fù)的代碼采记,所以我們使用享元模式來優(yōu)化一下代碼
- 提取公有部分和私有部分:這兩段相似的代碼它們的私有部分是接收拷貝的目標(biāo)和拷貝的來源是不同的佣耐,我們先把它們的不同點提取為外部的公有享元,把接收拷貝的目標(biāo)(extend第一個參數(shù))作為外部的享元唧龄,通過target存起來兼砖,然后把拷貝數(shù)據(jù)的來源也就是被拷貝者變成source變量
它們公有的部分是for in循環(huán),所以我們保留for in循環(huán)既棺,for in循環(huán)應(yīng)該循環(huán)我們的source讽挟,然后把sourse拷貝到target上面
這里依然要進行if else判斷,判斷如果參數(shù)長度等于1說明是給jQuery對象本身擴展屬性丸冕,就改變一下我們的享元耽梅,將target變成this,然后將sourse變成argument第一項胖烛;如果參數(shù)長度不等于1的話就說明要將第二個參數(shù)對象拷貝到目標(biāo)參數(shù)也就是第一個參數(shù)上褐墅,所以將target賦值為argument的第一項,將source變成argument第二項
(代碼勘誤:以上if判斷應(yīng)該是arguments.length == 1)
這樣就成功的把兩段for循環(huán)代碼減少為一段洪己,通過將不同的部分提取出來作為外部公用享元,然后只保留一段公用的操作竟贯,通過判斷來改變外部的公用享元應(yīng)該是哪個目標(biāo)答捕,有效的減少了重復(fù)代碼,這就是享元模式的妙用屑那。
3.2. 橋接模式的示例
3.2.1 創(chuàng)建不同的選中效果
需求:有一組菜單拱镐,上面每種選項都有不同的選中效果。
假設(shè)我們有三個菜單menu1持际、menu2沃琅、menu3,在常規(guī)情況下我們會先新建一個菜單類蜘欲,它接收一個文字內(nèi)容益眉,把文字內(nèi)容放到類屬性上面,然后創(chuàng)建div,將div的內(nèi)容設(shè)置為文字內(nèi)容郭脂,如:
在使用的時候會創(chuàng)建menu1年碘、menu2、menu3三個實例展鸡,將對應(yīng)的內(nèi)容傳進去屿衅。
然后給它們綁定不同的事件實現(xiàn)不同的效果
在不使用橋接模式的情況下,我們要創(chuàng)建三個對象莹弊,分別對這三個對象綁定不同的事件去改變顏色涤久,這樣的代碼重復(fù)率比較高,不符合高復(fù)用性原則忍弛。
使用橋接模式優(yōu)化上面的代碼:
- 提取公共部分:上面代碼的公共部分是設(shè)置顏色和事件綁定這塊响迂,我們將這塊提取出來然后橋接到源對象上:先在menuItem類中加入一個color屬性,再接收一個color參數(shù)(它是我們要橋接的對象)剧罩,然后將接收的color參數(shù)橋接到menuItem類的color屬性上
然后創(chuàng)建menuColor類栓拜,它接收兩個參數(shù)colorover(鼠標(biāo)懸停的顏色)、colorout(鼠標(biāo)移開的顏色)惠昔、分別把接收的兩個參數(shù)放在menuColor類的屬性上
因為dom已經(jīng)放在menuItem類的屬性上了幕与,所以我們可以通過一個方法來把dom事件綁定上去,我們給menuItem類的prototype添加一個bind方法镇防,它負責(zé)給dom綁定事件
綁定事件后我們不需要關(guān)心它到底要用哪個顏色啦鸣,只需要直接拿出橋接過來的顏色對象(this.color)就可以了,所以我們在事件綁定的外層創(chuàng)建self變量賦值為this来氧,因為事件中的this指向dom對象诫给,所以只需要在onmouseover事件中將this.style.color賦值為菜單對象也就是self.color對象上的colorOver屬性即可,onmouseout事件中同理啦扬。
這樣再去實現(xiàn)需求時中狂,我們只需要定義一個外部數(shù)據(jù)數(shù)組,這個外部數(shù)據(jù)定義了菜單的文字扑毡、懸停和移出的顏色胃榕,使用時循環(huán)這個數(shù)組創(chuàng)建menuItem實例,傳入數(shù)據(jù)的內(nèi)容瞄摊,然后創(chuàng)建我們要橋接過去的顏色對象告訴它懸停和移除的顏色是什么勋又,并將這個對象傳入menuItem實例。最后調(diào)用bind方法將事件自動綁定上去换帜。
通過對比可以發(fā)現(xiàn)我們的重復(fù)代碼變得更少了楔壤,代碼的復(fù)用性更好了,這就是橋接模式的作用惯驼。面臨這樣的問題時蹲嚣,我們通過把它們的變化部分和不變部分分離递瑰,再橋接到一起來應(yīng)對后面多維度的變化,這就是橋接模式的目的和它帶來的好處端铛。
3.2.2. Express中創(chuàng)建get等方法
需求:express中有g(shù)et泣矛、post等等方法,有七八個禾蚕,如何方便快速的創(chuàng)建您朽。
比如我們可以在express中通過app.get來設(shè)置一個get請求的中間件、通過app.post來設(shè)置一個post請求的中間件换淆、可以通過app.delete來設(shè)置一個delete請求的中間件哗总,我們要給這個實例app賦予這些方法
先看一個反面示例:
很多人會這樣入手,創(chuàng)建一個express類倍试,給它的prototype上添加get讯屈、post、delete方法
這是一個很典型的我們的系統(tǒng)可能會朝著多維度發(fā)展的例子县习,因為后期可能還要添加put等等請求方式涮母,這些請求方式之間有非常相似的部分,這樣就會重復(fù)的往原型鏈上添加方法躁愿,造成很多重復(fù)代碼叛本,如何去優(yōu)化呢?
express源碼中是這樣做的彤钟,它首先會有一個methods數(shù)組来候,這個數(shù)組在源碼中是通過一個第三方庫然后require進來的,演示代碼中我們就直接創(chuàng)建這個數(shù)組逸雹,將幾個有代表性的請求方法名稱寫入數(shù)組营搅,然后循環(huán)這個數(shù)組,在循環(huán)體內(nèi)給express實例去注冊這些方法
這樣我們就不用重復(fù)寫那么多方法了梆砸,關(guān)于具體的功能转质,它借助一個route對象將功能橋接過來,直接在注冊的方法里面調(diào)用route[method]然后傳入?yún)?shù)
route里面也是類似的一個循環(huán)帖世,把源碼拷過來
可以看到route里面的methods也是通過一個循環(huán)來注入的峭拘,循環(huán)內(nèi)部根據(jù)我們是什么樣的方法進行對應(yīng)的操作,調(diào)用對應(yīng)的中間件狮暑,這樣就非常有效的減少了重復(fù)代碼,提高了代碼的可復(fù)用性
這種做法相當(dāng)于直接調(diào)用get或者post辉饱,然后這個get和post利用橋接過來的route對象上的方法來完成功能搬男,而route對象上的方法也是通過橋接來完成的,在route內(nèi)部橋接的其實就是上面源碼中一整段的function彭沼,在這個function中來判斷方法是什么缔逛,調(diào)用對應(yīng)方法的中間件
以上就是橋接模式在express中優(yōu)化代碼的應(yīng)用。
3.3. 模板方法模式的示例
3.3.1. 編寫一個彈窗組件
需求:項目有一系列彈窗,每個彈窗的行為褐奴、大小按脚、文字都不相同。
假如我們寫一個消息型彈窗敦冬、發(fā)送請求型的彈窗辅搬、刪除操作型的彈窗
以常規(guī)的思維我們可能會新建一個消息型彈窗類、發(fā)送請求型的彈窗類脖旱、刪除操作型的彈窗類堪遂,這種方式大可不必,雖然它們之間的行為萌庆、大小等不同溶褪,但是它們之間有非常多的共同點,比如說它們始終是一個彈窗践险、它們要彈出猿妈、點擊確定或者取消它們都要消失等,這是它們的共同點巍虫,參照模板方法模式的思想彭则,把他們的共同點先提取出一個基礎(chǔ)模板類,基礎(chǔ)模板類中定義word垫言、size贰剥、dom屬性,分別賦值為傳入的word和size筷频,dom初始化為null
然后定義基礎(chǔ)的行為方法如顯示彈窗的初始化蚌成,在方法體內(nèi)創(chuàng)建div,把div的文字賦值為this.word凛捏,div的樣式賦值為size的屬性担忧,這是每個彈窗都有的,它必須有一定的寬高和文字坯癣,再把this.dom賦值為這個div
然后定義基本操作的方法比如所有的彈窗點擊取消之后都要隱藏瓶盛,方法體內(nèi)讓div的display變?yōu)閚one
當(dāng)然我們還有確定操作,但是我們沒辦法確定點擊確定之后它要干什么示罗,所以我們先定下確定操作的基礎(chǔ)行為惩猫,點擊確定首先也要隱藏彈窗
然后我們再定義一個特殊型彈窗,比如說定義一個ajax型的彈窗蚜点,點擊確定之后要發(fā)送一個ajax請求轧房。我們創(chuàng)建一個ajaxPop類,這個ajaxPop類繼承基礎(chǔ)類basePop(類的內(nèi)部通過call調(diào)用其他類可以實現(xiàn)繼承)
再擴展ajaxPop類的行為绍绘,將基礎(chǔ)類的實例賦值給ajaxPop類的prototype即可繼承基礎(chǔ)類的行為
然后獲取ajaxPop類之前的隱藏行為奶镶,再定義它新的隱藏行為方法袍辞,在新的方法里面先調(diào)用之前的隱藏行為方法笔横,再去加入ajaxPop類特殊的隱藏行為称鳞,比如它點擊取消之后要打印1(裝飾者模式的體現(xiàn))
確認型彈窗同理雅镊,先把之前的確認行為拿出來,然后再重寫它的確認行為捺信,在重寫的方法體內(nèi)調(diào)用之前的確認行為酌媒,再加入特殊的確認行為,比如要發(fā)送一個ajax請求残黑。(裝飾者模式的體現(xiàn))
這樣的方式下我們就可以非常好的以最少的代碼量去創(chuàng)建和擴展不同類型的彈窗馍佑,這種方式和面向?qū)ο笾械睦^承很類似,模板方法模式并不一定要通過繼承來實現(xiàn)梨水,有非常多的實現(xiàn)方式拭荤,它強調(diào)的并不是一定要有繼承和模板,而是強調(diào)先定義后面需要進行的一系列不同維度的操作的基本行為疫诽,然后在這個基本行為的操作上給出一個擴展的空間舅世,這就是模板方法模式的目的和作用。
3.3.2. 封裝一個算法計算器
需求:現(xiàn)在我們有一系列自己的算法奇徒,但是這個算法常在不同的地方需要增加一些不同的操作雏亚。
比如它在a頁面需要在計算之前讓兩個數(shù)相加,在b頁面需要在計算之前讓兩個數(shù)相減摩钙,也就是說這個算法計算器有一系列的基本算法罢低,這些基本算法又在不同的地方有不同的操作,這種需求就是非常典型的可以用模板方法模式來解決的例子胖笛。代碼示例:
首先我們創(chuàng)建一個counter類
定義一下counter方法的基礎(chǔ)計算也就是先把算法骨架搭出來网持,在prototype上添加count方法,這個count方法就是計算的時候調(diào)用的方法长踊,它會接收計算的數(shù)據(jù)
我們在這個方法里面先去定義一個基本方法baseCount功舀,假設(shè)baseCount先把num+4,再把num*4
這樣我們定義好了基礎(chǔ)計算身弊,模板方法模式是先定義好基礎(chǔ)辟汰,然后再去擴展,怎么去擴展基礎(chǔ)計算阱佛?
所以我們需要留出兩個擴展方法帖汞,對比上一個案例彈窗所演示的繼承方式,這里我們可以用方法組合的方式來完成擴展凑术。
先在counter類的prototype上定義兩個方法翩蘸,一個是基礎(chǔ)算法計算之前要進行的計算,一個是基礎(chǔ)算法計算之后要進行的計算
這兩個方法類似axios的請求攔截器和響應(yīng)攔截器麦萤,通過addBefore和addAfter添加一些方法鹿鳖,這些方法分別會在baseCount調(diào)用之前和之后來進行作用,所以我們需要在counter類中增加兩個隊列壮莹,用于存放基礎(chǔ)算法計算之前添加的方法和之后添加的方法翅帜。
然后分別在addBefore和addAfter方法里面push對應(yīng)的方法
有了擴展的方法之后我們需要改寫一下計算方法,讓它先執(zhí)行beforeCounter隊列命满,計算之后再執(zhí)行afterCounter隊列涝滴。
count方法內(nèi)先定義變量_resultnum,初始等于傳進來的num胶台,然后定義一個_arr變量歼疮,先將_arr初始化為[baseCount],這個_arr就是我們要執(zhí)行的方法隊列
然后我們將beforeCounter拼接_arr再拼接上afterCounter诈唬,這樣整個調(diào)用就形成了一個隊列beforeCounter => baseCount => afterCounter
接下來我們只需要從頭到尾依次執(zhí)行這個隊列韩脏,傳入數(shù)據(jù)進行計算,再將結(jié)果給_resultnum铸磅,所有的方法都執(zhí)行完后再將最終的計算結(jié)果_resultnum返回出去就可以了
代碼寫好之后赡矢,使用起來就非常簡單了,假設(shè)在a頁面基礎(chǔ)計算之前先減減阅仔,基礎(chǔ)計算之后再把數(shù)字乘以2吹散,我們可以先新建一個實例化對象,調(diào)用它的addBefore方法八酒,回調(diào)函數(shù)中進行減減操作再把計算結(jié)果返回空民;再調(diào)用addAfter方法,回調(diào)中將結(jié)果乘以2并返回羞迷;再去調(diào)用我們的基礎(chǔ)計算方法count把需要計算的數(shù)字傳入即可界轩。
這樣就保證了a頁面既有我們的基礎(chǔ)算法,又有它的特異性算法闭树。
上面的彈窗例子中使用的是繼承的方式耸棒,本例中使用組合的方式,把我們要擴展的東西變成方法組合到一起來達成擴展报辱,無論使用哪種方式它們都是去找到相似的部分与殃,然后定義基本的操作骨架,根據(jù)操作骨架再給出擴展接口碍现,這就是模板方法模式的核心思想幅疼。再次強調(diào)無論什么設(shè)計模式,我們一定要先記住它的核心思想昼接,而不是記住它的行為爽篷。
最后,我們來認識一下JavaScript的組合和繼承
- 組合
① JavaScript最初沒有專門的繼承慢睡,所以最初的JavaScript推崇函數(shù)式編程逐工,然后進行統(tǒng)一組合橋接到一起
② 橋接模式可以看成組合的一種體現(xiàn)铡溪,它把不同的東西組合到一起來產(chǎn)生一個新的對象或完整的功能,組合的好處是耦合低泪喊、復(fù)用方法方便棕硫、擴展方便,它的缺點就是要手動的去一個個組合袒啼,不能像繼承一樣自動完成
- 繼承
① 在ES6出現(xiàn)class和extend之前哈扮,繼承也可以實現(xiàn),實現(xiàn)的方式多種多樣蚓再,但都是各有弊端
② 模板方法模式可以看成繼承的一種體現(xiàn)滑肉,繼承的好處是可以自動獲得父類的內(nèi)容與接口,方便統(tǒng)一化摘仅,繼承的缺點就是不方便擴展靶庙,如果用子類去繼承父類,父類發(fā)生更改的時候子類也會發(fā)生更改实檀,這樣就非常不利于后續(xù)的擴展
通常來說組合大于繼承惶洲,我們更推崇于使用組合來代替繼承,能使用組合解決問題的話最好不要使用繼承膳犹。
下一篇:設(shè)計模式—關(guān)于提高可擴展性(方法層面)的學(xué)習(xí)(更加從容的應(yīng)對需求變更)
本文由博客一文多發(fā)平臺 OpenWrite 發(fā)布恬吕!