很多開發(fā)者在面對設(shè)計/架構(gòu)時,常常有想學(xué)但無從下手,學(xué)了又不會用的困擾。學(xué)習(xí)設(shè)計并不是只學(xué)習(xí)設(shè)計模式,在進行設(shè)計時,我們需要底層思想來支持,這里的底層思想其實就是設(shè)計原則,而設(shè)計原則則是面向?qū)ο?a target="_blank">編程基于現(xiàn)實背景衍生出來的一套規(guī)則,用來解決開發(fā)中的痛點。
一個好的架構(gòu)需要反復(fù)進行思考以及設(shè)計。
一、面向?qū)ο?/p>
什么是面向?qū)ο螅?先來看下基本定義:
面向?qū)ο笫且环N風(fēng)格,會以類作為代碼的基本單位,通過對象訪問,并擁有封裝、繼承、多態(tài)、抽象四種特性作為基石,可讓其更為智能。代表語言Java。
1. 四大特性(也有人說三種,不要糾結(jié))
?。?) 封裝
封裝也被稱為信息隱藏。類通過暴露有限的訪問接口,授權(quán)外部僅能通過類提供的方式(或者叫函數(shù))來訪問內(nèi)部信息或者數(shù)據(jù)。
將用戶信息隱藏在內(nèi)部,在確實需要訪問時,再通過暴露出來的唯一入口進行,這一過程就是封裝,合理運用封裝可以降低模塊間依賴關(guān)系(松耦合)。
(2) 繼承
“繼承”是面向?qū)ο笾械牡诙卣鳎w現(xiàn)了類與類之間的“is-a”關(guān)系。當(dāng)兩個類進行繼承關(guān)聯(lián)綁定的時候,子類自動具備來自于父類的屬性和行為。可以提升復(fù)用性解決模板代碼問題,提升開發(fā)效率的同時也解決了錯寫,漏寫帶來的問題。
?。?) 多態(tài)
一句話概括“多態(tài)”:一個對象有多種形態(tài)。
合理運用多態(tài)可以寫出易擴展的代碼,基于接口而非實現(xiàn)編程和開閉原則的核心
?。?) 抽象
抽象的目的是為了隱藏方法的具體實現(xiàn),讓調(diào)用者只需要關(guān)心方法提供了哪些方法(功能),并不需要知道這些功能是如何實現(xiàn)的。在Java中體現(xiàn)方式是接口和抽象類
(5) 接口和抽象類的區(qū)別
接口更側(cè)重于功能的設(shè)計,并且能將具體實現(xiàn)與調(diào)用者隔離,一般要以接口隔離原則設(shè)計接口及粒度越細越好
抽象類更側(cè)重于提升復(fù)用性,在原有的基礎(chǔ)上預(yù)留擴展點供開發(fā)者靈活實現(xiàn)
區(qū)別:接口可以降低模塊間耦合性,抽象類可提升復(fù)用性。
相同點:均有較好的擴展性,符合開閉原則
2. 誕生背景
談及面向?qū)ο蟊囟x不開面向過程,畢竟它就是由面向過程衍變而來,吸收其大部分優(yōu)點并解決其痛點。那什么是面向過程呢?基本定義如下:
分析出解決問題所需要的步驟,然后用函數(shù)把這些步驟一步一步實現(xiàn),使用的時候一個一個依次調(diào)用就可以了,更側(cè)重于功能的設(shè)計。代表語言C
面向?qū)ο笤诰幊讨靶枰谒拇筇匦詫δ茏鼋TO(shè)計,可以提高代碼安全性、復(fù)用性、擴展性,更易于維護。既然面向?qū)ο筮@么智能為什么面向過程語言還沒有被淘汰?其實面向?qū)ο笳Z言的智能是針對我們開發(fā)者的,為了能讓我們能寫出易于維護的代碼會多做一步設(shè)計,雖然離開發(fā)者更近了 但離機器卻遠了,畢竟機器只認識0和1而已。C語言規(guī)則簡單易于形成機器碼,所以執(zhí)行效率高,這也是其沒有被淘汰的原因。
二、六大設(shè)計原則才是一切設(shè)計的基石
設(shè)計原則是基于面向?qū)ο笏枷胙茏兂鰜淼囊恍┮?guī)則,用來解決實際開發(fā)中的一些痛點,是所有設(shè)計的底層思想,也是我個人認為是設(shè)計/架構(gòu)領(lǐng)域最重要的知識,所以請大家務(wù)必掌握好
?。?) 單一設(shè)計原則
單一原則很好理解,指一個函數(shù)或者一個類再或者一個模塊,職責(zé)越單一復(fù)用性就越強,同時能夠間接降低耦合性。
?。?) 開閉原則
一句話概括開閉原則:對擴展開放,修改關(guān)閉。它即充分詮釋抽象、多態(tài)特性,又是多數(shù)行為型設(shè)計模式的基礎(chǔ),遍布于各大優(yōu)秀框架之中,是最重要的一條設(shè)計原則,僅這一條原則就能把你的設(shè)計能力提高40%
?。?) 迪米特法則
基本概念:不該有直接依賴關(guān)系的模塊不要有依賴。有依賴關(guān)系的模塊之間,盡量只依賴必要的接口。迪米特法則很好理解并且非常實用,它和單一設(shè)計原則很像,前者符合松耦合后者符合高內(nèi)聚。
?。?) 接口隔離原則
基本概念:接口的調(diào)用者不應(yīng)該依賴它不需要的接口。乍一看與迪米特法則很相似。接口隔離原則與迪米特法則目的很相似,都可以降低模塊間依賴關(guān)系。但接口隔離更側(cè)重于設(shè)計單一接口,提升復(fù)用性并間接降低模塊間依賴關(guān)系,而迪米特法則是直接降低模塊間依賴關(guān)系。
(5) 里氏替換原則
基本概念:
設(shè)計子類的時候,要遵守父類的行為約定。父類定義了函數(shù)的行為約定,子類可以改變函數(shù)的內(nèi)部實現(xiàn)邏輯,但不能改變函數(shù)原有的行為約定。
里氏替換非常簡單并且很容易遵守,在使用繼承時,允許復(fù)寫父類方法,但不要改變其功能。比如自定義View,子類的onMeasure中一定要調(diào)用setMeasureaDimission()方法(或者直接使用super),否則會影響父類方法功能(會拋異常),也既違背了里氏替換原則。
?。?) 依賴倒置原則
控制反轉(zhuǎn): 提及依賴倒置便不得不提控制反轉(zhuǎn),一句話概括:將復(fù)雜的程序操作控制權(quán)由程序員交給成熟的框架處理,程序員-》成熟的框架為反轉(zhuǎn),框架應(yīng)暴露出擴展點由程序員實現(xiàn)。
什么是依賴倒置?
高層模塊(使用者)不應(yīng)依賴低層模塊(被使用者),它們共同依賴同一個抽象,抽象不要依賴具體實現(xiàn)細節(jié),具體實現(xiàn)細節(jié)依賴抽象。
其實核心點就是基于接口而非實現(xiàn)編程,高層模塊(業(yè)務(wù)層)不依賴于低層模塊(SQLiteDao/RoomDao),而是依賴于抽象(IDao),可見依賴倒置也是開閉原則擴展而來。 區(qū)別是依賴倒置更側(cè)重于指導(dǎo)框架的設(shè)計,框架層應(yīng)該盡量將更多的細節(jié)隱藏在內(nèi)部,對外只暴露抽象(抽象類/接口),指導(dǎo)框架設(shè)計這方面核心就是控制反轉(zhuǎn)。
責(zé)編AJX
評論
查看更多