您好,登錄后才能下訂單哦!
這篇文章主要介紹“什么是SOLID原則”,在日常操作中,相信很多人在什么是SOLID原則問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”什么是SOLID原則”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!
01 什么是 SOLID 原則
SOLID 原則其實是用來指導軟件設計的,它一共分為五條設計原則,分別是:
單一職責原則(SRP)
開閉原則(OCP)
里氏替換原則(LSP)
接口隔離原則(ISP)
依賴倒置原則(DIP)
單一職責原則(SRP)
單一職責原則(Single Responsibility Principle),它的定義是:應該有且僅有一個原因引起類的變更。簡單地說:接口職責應該單一,不要承擔過多的職責。 用生活中肯德基的例子來舉例:負責前臺收銀的服務員,就不要去餐廳收盤子。負責餐廳收盤子的就不要去做漢堡。
單一職責適用于接口、類,同時也適用于方法。例如我們需要修改用戶密碼,有兩種方式可以實現,一種是用「修改用戶信息接口」實現修改密碼,一種是新起一個接口來實現修改密碼功能。在單一職責原則的指導下,一個方法只承擔一個職能,所以我們應該新起一個接口來實現修改密碼的功能。
單一職責原則的重點在于職責的劃分,很多時候并不是一成不變的,需要根據實際情況而定。單一職責能夠使得類復雜性降低、類之間職責清晰、代碼可讀性提高、更加容易維護。但它的缺點也很明顯,就是對技術人員要求高,有些時候職責難以區分。
我們在設計一個類的時候,可以先從粗粒度的類開始設計,等到業務發展到一定規模,我們發現這個粗粒度的類方法和屬性太多,且經常修改的時候,我們就可以對這個類進行重構了,將這個類拆分成粒度更細的類,這就是所謂的持續重構。
開閉原則(OCP)
開閉原則(Open Closed Principle),它的定義是:一個軟件實體,如類、模塊和函數應該對擴展開放,對修改關閉。簡單地說:就是當別人要修改軟件功能的時候,使得他不能修改我們原有代碼,只能新增代碼實現軟件功能修改的目的。
這聽著有點玄乎,我來舉個例子吧。
這段代碼模擬的是對于水果剝皮的處理程序。如果是蘋果,那么是一種撥皮方法;如果是香蕉,則是另一種剝皮方法。如果以后還需要處理其他水果,那么就會在后面加上很多 if else 語句,最終會讓整個方法變得又臭又長。如果恰好這個水果中的不同品種有不同的剝皮方法,那么這里面又會有很多層嵌套。
if(type == apple){ //deal with apple } else if (type == banana){ //deal with banana } else if (type == ......){ //...... }
可以看得出來,上面這樣的代碼并沒有滿足「對拓展開放,對修改封閉」的原則。每次需要新增一種水果,都可以直接在原來的代碼上進行修改。久而久之,整個代碼塊就會變得又臭又長。
如果我們對剝水果皮這件事情做一個抽象,剝蘋果皮是一個具體的實現,剝香蕉皮是一個具體的實現,那么寫出的代碼會是這樣的:
public interface PeelOff { void peelOff(); } public class ApplePeelOff implement PeelOff{ void peelOff(){ //deal with apple } } public class BananaPeelOff implement PeelOff{ void peelOff(){ //deal with banan } } public class PeelOffFactory{ private Map<String, PeelOff> map = new HashMap(); private init(){ //init all the Class that implements PeelOff interface } } ..... public static void main(){ String type = "apple"; PeelOff peelOff = PeelOffFactory.getPeelOff(type); //get ApplePeelOff Class Instance. peelOff.pealOff(); }
上面這種實現方式使得別人無法修改我們的代碼,為什么?
因為當需要對西瓜剝皮的時候,他會發現他只能新增一個類實現 PeelOff 接口,而無法在原來的代碼上修改。這樣就實現了「對拓展開放,對修改封閉」的原則。
里氏替換原則(LSP)
里氏替換原則(LSP)的定義是:所有引用基類的地方必須能透明地使用其子類的對象。簡單地說:所有父類能出現的地方,子類就可以出現,并且替換了也不會出現任何錯誤。 例如下面 Parent 類出現的地方,可以替換成 Son 類,其中 Son 是 Parent 的子類。
Parent obj = new Son(); 等價于 Son son = new Son();
這樣的例子在 Java 語言中是非常常見的,但其核心要點是:替換了也不會出現任何的錯誤。這就要求子類的所有相同方法,都必須遵循父類的約定,否則當父類替換為子類時就會出錯。 這樣說可能還是有點抽象,我舉個例子。
public class Parent{ // 定義只能扔出空指針異常 public void hello throw NullPointerException(){ } } public class Son extends Parent{ public void hello throw NullPointerException(){ // 子類實現時卻扔出所有異常 throw Exception; } }
上面的代碼中,父類對于 hello 方法的定義是只能扔出空指針異常,但子類覆蓋父類的方法時,卻扔出了其他異常,違背了父類的約定。那么當父類出現的地方,換成了子類,那么必然會出錯。
其實這個例子舉得不是很好,因為這個在編譯層面可能就有錯誤。但表達的意思應該是到位了。
而這里的父類的約定,不僅僅指的是語法層面上的約定,還包括實現上的約定。有時候父類會在類注釋、方法注釋里做了相關約定的說明,當你要覆寫父類的方法時,需要弄懂這些約定,否則可能會出現問題。例如子類違背父類聲明要實現的功能。比如父類某個排序方法是從小到大來排序,你子類的方法竟然寫成了從大到小來排序。
里氏替換原則 LSP 重點強調:對使用者來說,能夠使用父類的地方,一定可以使用其子類,并且預期結果是一致的。
接口隔離原則(ISP)
接口隔離原則(Interface Segregation Principle)的定義是:類間的依賴關系應該建立在最小的接口上。簡單地說:接口的內容一定要盡可能地小,能有多小就多小。
舉個例子來說,我們經常會給別人提供服務,而服務調用方可能有很多個。很多時候我們會提供一個統一的接口給不同的調用方,但有些時候調用方 A 只使用 1、2、3 這三個方法,其他方法根本不用。調用方 B 只使用 4、5 兩個方法,其他都不用。接口隔離原則的意思是,你應該把 1、2、3 抽離出來作為一個接口,4、5 抽離出來作為一個接口,這樣接口之間就隔離開來了。
那么為什么要這么做呢?我想這是為了隔離變化吧! 想想看,如果我們把 1、2、3、4、5 放在一起,那么當我們修改了 A 調用方才用到 的 1 方法,此時雖然 B 調用方根本沒用到 1 方法,但是調用方 B 也會有發生問題的風險。而如果我們把 1、2、3 和 4、5 隔離成兩個接口了,我修改 1 方法,絕對不會影響到 4、5 方法。
除了改動導致的變化風險之外,其實還會有其他問題,例如:調用方 A 抱怨,為什么我只用 1、2、3 方法,你還要寫上 4、5 方法,增加我的理解成本。調用方 B 同樣會有這樣的困惑。
在軟件設計中,ISP 提倡不要將一個大而全的接口扔給使用者,而是將每個使用者關注的接口進行隔離。
依賴倒置原則(DIP)
依賴倒置原則(Dependence Inversion Principle)的定義是:高層模塊不應該依賴底層模塊,兩者都應該依賴其抽象。抽象不應該依賴細節,即接口或抽象類不依賴于實現類。細節應該依賴抽象,即實現類不應該依賴于接口或抽象類。簡單地說,就是說我們應該面向接口編程。通過抽象成接口,使各個類的實現彼此獨立,實現類之間的松耦合。
如果我們每個人都能通過接口編程,那么我們只需要約定好接口定義,我們就可以很好地合作了。軟件設計的 DIP 提倡使用者依賴一個抽象的服務接口,而不是去依賴一個具體的服務執行者,從依賴具體實現轉向到依賴抽象接口,倒置過來。
02 SOLID 原則的本質
我們總算把 SOLID 原則中的五個原則說完了。但說了這么一通,好像是懂了,但是好像什么都沒記住。 那么我們就來盤一盤他們之間的關系。ThoughtWorks 上有一篇文章說得挺不錯,文中說:
單一職責是所有設計原則的基礎,開閉原則是設計的終極目標。
里氏替換原則強調的是子類替換父類后程序運行時的正確性,它用來幫助實現開閉原則。
而接口隔離原則用來幫助實現里氏替換原則,同時它也體現了單一職責。
依賴倒置原則是過程式編程與面向對象編程的分水嶺,同時它也被用來指導接口隔離原則。
簡單地說:依賴倒置原則告訴我們要面向接口編程。當我們面向接口編程之后,接口隔離原則和單一職責原則又告訴我們要注意職責的劃分,不要什么東西都塞在一起。
當我們職責捋得差不多的時候,里氏替換原則告訴我們在使用繼承的時候,要注意遵守父類的約定。而上面說的這四個原則,它們的最終目標都是為了實現開閉原則。
到此,關于“什么是SOLID原則”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。