概述
熟練掌握和應(yīng)用面向?qū)ο笤O(shè)計(jì)(Object Oriented Design,OOD)7大原則,是初/中級(jí)JAVA工程師向高級(jí)/資深工程師進(jìn)階的一個(gè)必備技能,它可以大大提升程序的可復(fù)用性和可維護(hù)性,也是重構(gòu)代碼的一大利器。7大設(shè)計(jì)原則包括開閉原則、里氏替換原則、依賴倒轉(zhuǎn)原則、單一職責(zé)原則、接口隔離原則、組合/聚合復(fù)用原則、迪米特法則。
1.開閉原則
面向?qū)ο罂蓮?fù)用設(shè)計(jì)原則中最基礎(chǔ)的原則便是開閉原則(Open-Closed Principle,OCP)。開閉原則指的是在設(shè)計(jì)一個(gè)對(duì)象(類、模塊、函數(shù))時(shí),應(yīng)遵循或做到對(duì)擴(kuò)展開放、對(duì)修改關(guān)閉,其核心思想是面向接口/抽象進(jìn)行編程。比如第四方支付平臺(tái),集成微信支付服務(wù)時(shí),遵循開閉原則的話,正常的做法就是先抽象設(shè)計(jì)一個(gè)支付接口,然后微信支付類實(shí)現(xiàn)該支付接口。以后平臺(tái)集成更多如支付寶、華為、蘋果等支付服務(wù)時(shí),只需要擴(kuò)展一個(gè)對(duì)應(yīng)支付方式的支付類即可,這樣既擴(kuò)展了新的支付服務(wù),同時(shí)避免了修改現(xiàn)有的支付接口以及微信支付類,最大限度保證了新代碼不會(huì)影響現(xiàn)有的業(yè)務(wù)代碼。這就是對(duì)擴(kuò)展(新對(duì)象)開放,對(duì)修改(現(xiàn)有對(duì)象)關(guān)閉。
2.里氏替換原則
里氏替換原則(Liskov Substitution Principle,LSP)要求設(shè)計(jì)一個(gè)對(duì)象時(shí),代碼中任何父類對(duì)象可以出現(xiàn)的地方,子類都可以出現(xiàn),即可以使用子類來(lái)代替父類。實(shí)現(xiàn)開閉原則的核心思想是面向接口/抽象進(jìn)行編程,其關(guān)鍵步驟是抽象化,而父類和子類的繼承關(guān)系就是抽象化的具體體現(xiàn),所以里氏替換原則是對(duì)實(shí)現(xiàn)抽象化的具體步驟的規(guī)范,它是對(duì)開閉原則的補(bǔ)充。比如教學(xué)平臺(tái)中新增加了學(xué)生用戶Student,和教師用戶Teacher一樣進(jìn)入個(gè)人中心,都需要登錄,在設(shè)計(jì)或重構(gòu)用戶登錄服務(wù)類時(shí),抽象的用戶User類作為教師Teacher和學(xué)生Student的父類,此時(shí)需要遵循出現(xiàn)用戶User的地方,都可以使用新擴(kuò)展的學(xué)生Student代替,當(dāng)然也必須也可以使用教師Teacher代替,這樣設(shè)計(jì)出來(lái)的User類,對(duì)用戶登錄服務(wù)類來(lái)說(shuō),后續(xù)擴(kuò)展更多的用戶User的子類比如家長(zhǎng)、輔導(dǎo)員時(shí),可以保證符合開閉原則。
3.依賴倒轉(zhuǎn)原則
依賴倒轉(zhuǎn)原則(Dependency Inversion Principle,DIP)指程序中要依賴抽象(接口/抽象類)而不是具體的實(shí)現(xiàn)(實(shí)現(xiàn)類)進(jìn)行編程,即面向接口/抽象進(jìn)行編程,這樣可以最大程度降低模塊之間的耦合。比如訂單服務(wù)中,會(huì)調(diào)用(依賴)支付服務(wù)以完成訂單的支付。此時(shí)的訂單服務(wù)實(shí)現(xiàn)類代碼中,聲明或持有的應(yīng)該是一個(gè)支付服務(wù)PayService接口,而不是具體實(shí)現(xiàn)類比如Alipay或WeChatPay,所有需要用到支付服務(wù)的地方,調(diào)用的都是PayService接口變量,即代碼中都是接口,等到在運(yùn)行時(shí)才實(shí)例化或注入具體的實(shí)現(xiàn)類,編寫代碼時(shí)不需要關(guān)心具體實(shí)現(xiàn)類,也就是面向接口/抽象編程。這樣,在應(yīng)用程序擴(kuò)展或集成新的支付服務(wù)時(shí),原來(lái)的訂單服務(wù)代碼可以不需要進(jìn)行修改任何代碼,這樣也就符合了開閉原則。
4.單一職責(zé)原則
單一職責(zé)原則(Single Function Principle,SFP)又稱單一功能原則,它規(guī)范設(shè)計(jì)一個(gè)類應(yīng)只實(shí)現(xiàn)單一或獨(dú)立的職責(zé)即業(yè)務(wù)功能。職責(zé)分明的設(shè)計(jì),可以提高程序的可維護(hù)性。如果多個(gè)獨(dú)立的業(yè)務(wù)功能設(shè)計(jì)在同一類中,當(dāng)一個(gè)或多個(gè)業(yè)務(wù)功能擴(kuò)展或變動(dòng)需要修改代碼時(shí),可能會(huì)帶來(lái)沖突問題,降低可維護(hù)性。比如訂單服務(wù)中,又包含了用戶服務(wù),重構(gòu)用戶服務(wù)的代碼時(shí),相當(dāng)于重構(gòu)訂單服務(wù)的代碼,這是不合理的,容易造成混淆。
5.接口隔離原則
接口隔離原則(Inteface Segregation Principle,ISP)指設(shè)計(jì)時(shí)不同的功能應(yīng)定義在不同的接口上,避免實(shí)現(xiàn)類依賴不需要的接口,換個(gè)角度理解就是一個(gè)類應(yīng)該依賴盡量少的接口或?qū)崿F(xiàn)類,減少程序的冗余性和復(fù)雜性。
6.組合/聚合復(fù)用原則
組合/聚合復(fù)用原則(Composition/Aggregation Principle,CARP)也叫做合成復(fù)用原則(Composition Reuse Principle,CRP),它指在一個(gè)新的對(duì)象中引入/注入現(xiàn)有的對(duì)象以達(dá)到功能復(fù)用和擴(kuò)展的目的。簡(jiǎn)單講就是盡量使用組合/聚合而不要使用繼承。
7.迪米特法則
迪米特法則(Low of Demeter,LoD)指設(shè)計(jì)一個(gè)對(duì)象時(shí),盡可能少的與其它對(duì)象發(fā)生相互作用,即盡可能少的了解或依賴其它對(duì)象,降低耦合度。廣義的迪米特法則,在類設(shè)計(jì)的具體操作上,主要通過(guò)以下三點(diǎn)來(lái)體現(xiàn)
- 優(yōu)先考慮將一個(gè)類設(shè)置為final不變類
- 盡量降低一個(gè)類及其成員變量的訪問權(quán)限
- 謹(jǐn)慎使用序列化