敖丙的代碼,有點(diǎn)離譜
我是3y,一年CRUD經(jīng)驗(yàn)用十年的markdown程序員???????常年被譽(yù)為職業(yè)八股文選手。
以前敖丙找過我看過幾次線上的問題,我看了他不少的代碼,還不錯(cuò),我偷師學(xué)了很多。
有不少的小伙伴都想要我來講講austin用到的設(shè)計(jì)模式,今天來簡(jiǎn)單聊聊,這也是面試經(jīng)常會(huì)被問到的。
設(shè)計(jì)模式這東西,說實(shí)話我也沒學(xué)全,一般我是遇到了相關(guān)的代碼再去學(xué)具體的設(shè)計(jì)模式。有了相關(guān)的設(shè)計(jì)模式的思想和應(yīng)用場(chǎng)景,就多琢磨下自己的代碼能不能寫得更好,實(shí)踐一把。
平時(shí)多留個(gè)心眼,覺得人家的代碼寫得有點(diǎn)秀,就想想是不是使用了設(shè)計(jì)模式。如果是的話,那就探討下該設(shè)計(jì)模式的應(yīng)用場(chǎng)景看后面自己能不能用得上
不多BB了,來吧。

01、責(zé)任鏈模式
我在「消息統(tǒng)一接入層」那里使用了責(zé)任鏈模式,用責(zé)任鏈模式的好處就是分工明確、解耦、易維護(hù)。
1、將多個(gè)條件判定分散到各個(gè)的處理類上,相對(duì)于if else耦合性相對(duì)較低。
2、增加一個(gè)具體的Handler處理類,不會(huì)影響到BaseHandler的代碼
責(zé)任鏈模式的缺點(diǎn):
1、項(xiàng)目里邊會(huì)有多個(gè)具體Handler類(因?yàn)槊糠N處理都抽象為一個(gè)類,所以會(huì)有多個(gè)類)
2、初看代碼時(shí)不太好閱讀(對(duì)外只是一個(gè)doChain方法,而里邊由多個(gè)處理類來組成,還得看相應(yīng)的調(diào)用順序)


責(zé)任鏈配置入口:com.java3y.austin.service.api.impl.config.PipelineConfig
責(zé)任鏈處理入口:com.java3y.austin.service.api.impl.service.SendServiceImpl#send
02、模板方法模式
在austin項(xiàng)目代碼上用到模板方法的地方還是蠻多的,比較有代表性的就是去重的功能。老讀者可能都知道,我認(rèn)為去重的功能的核心無非是唯一Key+存儲(chǔ)

模板方法模式要點(diǎn):
1、把公共的代碼抽取出來,如果該功能是不確定的,那我們將其修飾成抽象方法。
2、將幾個(gè)固定步驟的功能封裝到一個(gè)方法中,對(duì)外暴露這個(gè)方法,就可以非常方便調(diào)用了。
模板方法模式優(yōu)點(diǎn):封裝不變的部分,擴(kuò)展可變的部分。把認(rèn)為是不變的部分的算法封裝到父類,可變部分的交由子類來實(shí)現(xiàn)。
模板方法模式缺點(diǎn):抽象類定義了部分抽象方法,這些抽象的方法由子類來實(shí)現(xiàn),子類執(zhí)行的結(jié)果影響了父類的結(jié)果(子類對(duì)父類產(chǎn)生了影響),會(huì)帶來閱讀代碼的難度!
我們?cè)趯?shí)際寫代碼的時(shí)候,一般存儲(chǔ)和和步驟都已經(jīng)確認(rèn)下來了,唯一Key則可以由子類實(shí)現(xiàn)

模板方法模式的代碼1:com.java3y.austin.handler.deduplication.service.AbstractDeduplicationService#deduplication
模板方法模式的代碼2:com.java3y.austin.handler.handler.BaseHandler#doHandler
03、構(gòu)建者模式
建造者模式更多的是寫法上的不同,從代碼結(jié)構(gòu)層面上其實(shí)沒有很大的區(qū)別,只是看起來會(huì)更清爽一些。我借助了Lombok,在類上加上一個(gè)注解@Builder就可以使用建造者模式的代碼了,非常方便

在austin里就隨處可見了,各種builder鏈?zhǔn)秸{(diào)用。
04、策略模式
嚴(yán)格意義上的策略模式是基本沒什么人用的(策略模式有一個(gè)Context上下文對(duì)象),但如果我們說JDK線程池的設(shè)計(jì)也是策略模式

那我可以認(rèn)為的是:只要我們是面向接口編程的,那多多少少都有「策略模式」的影子
所以,austin項(xiàng)目使用了策略模式還是有不少的

策略模式代碼入口:com.java3y.austin.handler.pending.Task#run
05、生產(chǎn)者消費(fèi)者模式
生產(chǎn)者消費(fèi)者模式這種「設(shè)計(jì)模式」我還看到過在面試上讓手寫的,像JDK線程池的實(shí)現(xiàn)我認(rèn)為就是典型的生產(chǎn)者和消費(fèi)者模式(將消息丟入工作隊(duì)列,然后從工作隊(duì)列里消費(fèi))。
我在實(shí)現(xiàn)延遲消費(fèi)做批量的時(shí)候也實(shí)現(xiàn)了生產(chǎn)者和消費(fèi)者模式,場(chǎng)景主要就是我讀取文件的每一行記錄,積攢到一定的程度才進(jìn)行消費(fèi)。

生產(chǎn)者入口:com.java3y.austin.cron.service.impl.TaskHandlerImpl#handle
消費(fèi)者入口:com.java3y.austin.support.pending.AbstractLazyPending#initConsumePending
06、單例模式
單例模式和代理模式幾乎都是依賴Spring環(huán)境下去玩的了,基本都不用手寫。
在Spring下普通創(chuàng)建的對(duì)象默認(rèn)都是單例模式,在項(xiàng)目里也有部分的對(duì)象是需要多例的。
比如com.java3y.austin.handler.receiver.Receiver(不同的渠道不同的類型開不同的消費(fèi)者組)和com.java3y.austin.cron.pending.CrowdBatchTaskPending(數(shù)據(jù)需各自維護(hù),線程安全問題)

07、代理模式
代理模式在austin下倒是沒自己寫過,用的小組件幾乎都是基于代理模式去搞的。之前提及過的優(yōu)雅打印日志注解,只要你去看源碼,就一定會(huì)發(fā)現(xiàn)他們用的都是Spring的動(dòng)態(tài)代理去實(shí)現(xiàn)的。

看懂了,就說這組件是你自己優(yōu)化寫的。

后面austin更多的面試細(xì)節(jié),我會(huì)陸續(xù)繼續(xù)補(bǔ)充,歡迎點(diǎn)個(gè)star持續(xù)關(guān)注我的項(xiàng)目,不會(huì)讓你失望的
http://gitee.com/zhongfucheng/austin
目前還有我的個(gè)人微信還有少量名額可拉進(jìn)austin項(xiàng)目交流群,想進(jìn)來的添加我下方的二維碼,備注【項(xiàng)目】即可,拒絕內(nèi)鬼?????♀?
閱讀原文可跳轉(zhuǎn)至Austin倉庫
