
原創(chuàng)聲明
本文作者:黃小斜
轉(zhuǎn)載請(qǐng)務(wù)必在文章開(kāi)頭注明出處和作者。
系列文章介紹
本系列文章主要圍繞程序員,特別是Java或者后端程序員必須掌握的一些技術(shù)和技能,這些文章都是結(jié)合我個(gè)人的編程學(xué)習(xí)經(jīng)歷,總結(jié)和沉淀下來(lái)的方法論。作者目前在阿里做Java,忙里偷閑分享一些技術(shù)文章,希望能讓更多人更容易地學(xué)習(xí)編程。
系列文章將會(huì)把一些技術(shù)學(xué)習(xí)方法、過(guò)程、要領(lǐng)與我的學(xué)習(xí)經(jīng)驗(yàn)相結(jié)合,更加淺顯易懂,并且我也會(huì)把我學(xué)習(xí)時(shí)用的資料,書籍和文章拿出來(lái)分享給大家,節(jié)省你我的時(shí)間。所謂授人以魚也要授人以漁,是本系列文章希望達(dá)到的目標(biāo)。
一個(gè)熱愛(ài)分享的程序員,一個(gè)愛(ài)生活的斜杠青年。分享程序員編程學(xué)習(xí)干貨和個(gè)人成長(zhǎng)心得,期待你的關(guān)注,讓我們一起進(jìn)步!
本文思維導(dǎo)圖

什么是設(shè)計(jì)模式
學(xué)習(xí)編程的朋友,想必對(duì)于設(shè)計(jì)模式這個(gè)詞并不陌生,至少你一定也聽(tīng)說(shuō)過(guò),如果你是做Java的,那么就更加需要了解設(shè)計(jì)模式了,為什么這么說(shuō)呢,因?yàn)镴ava作為一門面向?qū)ο笳Z(yǔ)言,很多代碼都可以通過(guò)設(shè)計(jì)模式得到簡(jiǎn)化、規(guī)范,提升編碼效率和可讀性。
按照百度百科的說(shuō)法,軟件設(shè)計(jì)模式(Design pattern),又稱設(shè)計(jì)模式,是一套被反復(fù)使用、多數(shù)人知曉的、經(jīng)過(guò)分類編目的、代碼設(shè)計(jì)經(jīng)驗(yàn)的總結(jié)。使用設(shè)計(jì)模式是為了可重用代碼、讓代碼更容易被他人理解、保證代碼可靠性、程序的重用性。
也就是說(shuō),代碼可復(fù)用性是設(shè)計(jì)模式的核心要義。
平時(shí)我們聽(tīng)說(shuō)過(guò)的設(shè)計(jì)模式有哪些呢,比如工廠模式,單例模式,代理模式,觀察者模式等等,這些設(shè)計(jì)模式不僅在面試經(jīng)常問(wèn)到,而且在Java生態(tài)中也得到了廣泛的應(yīng)用,比如JDK里就有很多單例、工廠模式的應(yīng)用,spring框架基本上也都用到了這幾個(gè)設(shè)計(jì)模式,而Tomcat這種web應(yīng)用容器,也是集設(shè)計(jì)模式之大成,對(duì)于觀察者模式的應(yīng)用特別多。
為什么要學(xué)習(xí)設(shè)計(jì)模式
那么,我們學(xué)習(xí)設(shè)計(jì)模式有什么用呢,一來(lái),是幫助你更好地在日常開(kāi)發(fā)中使用到設(shè)計(jì)模式,二來(lái),想要理解JDK、spring以及Tomcat的實(shí)現(xiàn)原理和源碼,你就必須要掌握相關(guān)的設(shè)計(jì)模式,否則你連代碼都看不懂,又哪里談得上開(kāi)發(fā)呢。
這一點(diǎn)我體會(huì)很深,在大公司里,很多核心系統(tǒng)的代碼都寫得非常的高端大氣上檔次,對(duì)于設(shè)計(jì)模式的使用可以說(shuō)是用到了極致,像是模板方法、策略模式、工廠模式等等適用于大型應(yīng)用開(kāi)發(fā)的一些設(shè)計(jì)模式,都會(huì)得到廣泛的應(yīng)用。先看懂代碼,再進(jìn)行開(kāi)發(fā),這肯定是程序員的自我修養(yǎng)之一。
學(xué)習(xí)設(shè)計(jì)模式,短期利于面試,長(zhǎng)期則可以應(yīng)用于工作,看來(lái)對(duì)設(shè)計(jì)模式的學(xué)習(xí),已經(jīng)是刻不容緩了。
新手上路
對(duì)于新手來(lái)說(shuō),設(shè)計(jì)模式完全是陌生的事物,一般常見(jiàn)的20多個(gè)設(shè)計(jì)模式,能夠記住它的名字和用法都已經(jīng)很困難了,更不用說(shuō)自己能不能懂得如何去使用了。
我剛學(xué)設(shè)計(jì)模式的時(shí)候,就是抱著一本書啃半天,看完了所有的設(shè)計(jì)模式,但是過(guò)幾天就忘得差不多了,面試的時(shí)候問(wèn)我工廠模式,觀察者模式,還是支支吾吾半天答不上來(lái),說(shuō)白了就是沒(méi)有理解。
比如這個(gè)工廠模式,就分為簡(jiǎn)單工廠,工廠模式,以及抽象工廠模式,每個(gè)模式的用法都不太一樣,當(dāng)時(shí)就困擾了我很長(zhǎng)一段時(shí)間。
如果你理解了它的內(nèi)涵之后,就可以大概知道,簡(jiǎn)單工廠就是用來(lái)生成單一實(shí)例的,而工廠模式是可以根據(jù)輸入輸出不同的實(shí)例,抽象工廠則是根據(jù)不同的工廠生成不同產(chǎn)品的實(shí)例。
我們學(xué)習(xí)設(shè)計(jì)模式的時(shí)候,往往書本上給的栗子和demo都比較不切合實(shí)際,有的例子是動(dòng)物,有的例子是食物,這個(gè)時(shí)候,如果我們自己去寫一寫,替換成工作中的一些場(chǎng)景,或者是自己熟悉的場(chǎng)景,比如說(shuō)蔡徐坤,奧利給等等,相信更有助于你的理解和記憶。
花一些時(shí)間,跟著《head first 設(shè)計(jì)模式》這本書,把書上的設(shè)計(jì)模式案例都實(shí)現(xiàn)一下,能夠跑得起來(lái),要比你一遍一遍地看書來(lái)得靠譜多了。
學(xué)習(xí)源碼
很多朋友看到“源碼”兩個(gè)字就望而卻步,就好像讓你玩游戲你一百個(gè)答應(yīng),讓你拆開(kāi)機(jī)箱看看哪塊電路板因?yàn)橥嬗螒蚨鴩?yán)重發(fā)熱,你就完全提不起興趣。
學(xué)習(xí)設(shè)計(jì)模式,除了實(shí)戰(zhàn)以外,最好的方式就是去看一些源碼,比如JDK的源碼,Spring的源碼,甚至是Tomcat的源碼。
如果你自己啃不動(dòng),那也可以跟著一些書籍和博客去啃,網(wǎng)上隨便一搜就是一大把,spring里的xx設(shè)計(jì)模式、Tomcat里常見(jiàn)的n種設(shè)計(jì)模式,JDK里的20種設(shè)計(jì)模式等等,可能你平時(shí)都沒(méi)有注意,一看自己平時(shí)用的API里居然有這么多設(shè)計(jì)模式,你就會(huì)覺(jué)得很有意思了。
舉個(gè)栗子,JDK里的IO流,就使用了裝飾者模式,比如對(duì)于一個(gè)IO輸出流,它可能是字節(jié)流,也可能是字符流,它還可以是帶緩沖的輸出流,而這些特性都是通過(guò)裝飾者模式實(shí)現(xiàn)的,IO流的實(shí)例可以不斷的被轉(zhuǎn)化成另一種流,只需要通過(guò) “(裝飾物)IO流”這種寫法就可以不斷地進(jìn)行包裝,就好像你買了一杯奶茶,可以往里面加椰果,加波霸,加奶加糖一樣。
spring里最常用的幾個(gè)設(shè)計(jì)模式就是單例模式,代理模式。大家都知道spring的IOC和AOP,spring本身提供一個(gè)bean容器,而每個(gè)bean其實(shí)都是單例的(同一個(gè)堆里只有一個(gè)實(shí)例)這其實(shí)就是用了單例模式來(lái)實(shí)現(xiàn)的。
那么,AOP用的是什么設(shè)計(jì)模式呢,其實(shí)就是代理模式,AOP是通過(guò)動(dòng)態(tài)代理來(lái)實(shí)現(xiàn)的,首先,AOP是作用于某些方法或者是某些類的,你可以把這些方法或者類當(dāng)成一個(gè)切面,也就是被代理的對(duì)象,而我們希望在這個(gè)切面上添加的功能,就是代理對(duì)象,比如統(tǒng)一的登錄管理,請(qǐng)求攔截,安全檢查等功能。如果你了解過(guò)動(dòng)態(tài)代理,應(yīng)該就會(huì)理解我的這個(gè)描述。
而對(duì)于Tomcat來(lái)說(shuō),設(shè)計(jì)模式就更多了,我們這里只講一個(gè)觀察者模式,Tomcat的啟動(dòng)是有一個(gè)生命周期(pipeline)的,你可以把這個(gè)生命周期當(dāng)成一系列要執(zhí)行的方法,而Tomcat的實(shí)現(xiàn)允許你監(jiān)聽(tīng)這些方法的調(diào)用,你可以在pipeline上面注冊(cè)自己的監(jiān)聽(tīng)器,每當(dāng)pipeline執(zhí)行到你監(jiān)聽(tīng)的方法時(shí),它們就會(huì)通知你,然后你去執(zhí)行相應(yīng)的動(dòng)作。
不得不說(shuō),設(shè)計(jì)模式在Java生態(tài)中的應(yīng)用實(shí)在是太多了,當(dāng)然,理解設(shè)計(jì)模式這件事于是需要你花一定時(shí)間的。
結(jié)合工作
理解抽象的事物往往都是具有挑戰(zhàn)性的。學(xué)習(xí)設(shè)計(jì)模式,我們一般都是看書或者看教程,一般會(huì)有對(duì)一個(gè)模式的介紹,以及相應(yīng)的代碼,既然有代碼實(shí)現(xiàn),那就不能算是太抽象的東西,不過(guò),這些樣例代碼往往和我們開(kāi)發(fā)工作中的實(shí)現(xiàn)相去甚遠(yuǎn),所以,我們學(xué)習(xí)設(shè)計(jì)模式的時(shí)候也往往會(huì)學(xué)了就忘,更無(wú)法應(yīng)用到開(kāi)發(fā)工作中。
在工作中,有一項(xiàng)神秘的技能,可以讓你的代碼能力突飛猛進(jìn),讓你的代碼質(zhì)量、規(guī)范,以及可復(fù)用程度大大提升,這項(xiàng)神秘的技能,其實(shí)就是CV,沒(méi)錯(cuò),就是復(fù)制粘貼。
什么?不就是抄代碼嗎,我上我也行啊。不不不,程序員的事怎么能叫抄呢,那叫學(xué)習(xí)!參考!復(fù)用!
不過(guò),在大公司里,CV這件事雖然可恥但是有用,畢竟大廠里的大牛多,代碼寫的好的人也多,每個(gè)團(tuán)隊(duì)都有那么些神仙代碼,值得我們效仿學(xué)習(xí),我就經(jīng)??吹揭恍┐a,是好幾年前的大牛寫的,被一直傳承到現(xiàn)在,有時(shí)候即使要做重構(gòu)或者是做遷移,都要把這些大牛的核心代碼繼續(xù)搬過(guò)來(lái),可見(jiàn)這類優(yōu)質(zhì)代碼的影響力之大。
我們先不管這些牛人的代碼是怎么寫出來(lái)的,但是這些優(yōu)質(zhì)的典范確實(shí)值得我們學(xué)習(xí),比如我在開(kāi)發(fā)一個(gè)系統(tǒng)的時(shí)候,發(fā)現(xiàn)里面的核心業(yè)務(wù)代碼都是通過(guò)模板方法+注解化配置的方式來(lái)進(jìn)行開(kāi)發(fā)的,于是從頭到尾看了一遍,十分佩服,覺(jué)得自己一定寫不出來(lái),那么這種代碼風(fēng)格就可以借鑒到另一個(gè)系統(tǒng)中。
比如最近我全程負(fù)責(zé)另一個(gè)系統(tǒng)的開(kāi)發(fā),我自己可以定義規(guī)范和風(fēng)格,那么我當(dāng)然要大展身手了,于是,這些優(yōu)質(zhì)的代碼模板和設(shè)計(jì)風(fēng)格就都被我拿來(lái)參考了,畢竟,在大公司里盡量不要重復(fù)造輪子,多借鑒多學(xué)習(xí)一定是沒(méi)有壞處的,等到你掌握了這些東西的內(nèi)核之后,自己再去創(chuàng)造一套規(guī)范和風(fēng)格也未嘗不可。
其實(shí),不僅是設(shè)計(jì)模式,還有很多東西都是可以這樣通過(guò)模仿來(lái)學(xué)習(xí)的,比如架構(gòu)的設(shè)計(jì),系統(tǒng)的分析,技術(shù)棧的選擇等等,所謂書讀百遍其義自見(jiàn),熟讀唐詩(shī)三百首,不會(huì)做詩(shī)也會(huì)吟,講究的就是一個(gè)“熟能生巧”吧。
推薦資源
書籍
《head first設(shè)計(jì)模式》
《大話設(shè)計(jì)模式》