软件设计的原则
了解設(shè)計(jì)模式的朋友們,想必都聽說過“六大設(shè)計(jì)原則”吧。其實(shí)最經(jīng)典的 23 種設(shè)計(jì)模式中或多或少地都在使用這些設(shè)計(jì)原則,也就是說,設(shè)計(jì)模式是站在設(shè)計(jì)原則的基礎(chǔ)之上的。所以在學(xué)習(xí)設(shè)計(jì)模式之前,很有必要對這些設(shè)計(jì)原則先做一下了解。
GoF(四人幫),傳說中的四位大神們,他們聯(lián)手搞出了一套設(shè)計(jì)模式,堪稱 OOD(面向?qū)ο笤O(shè)計(jì))的經(jīng)典之作!震驚了整個(gè)軟件開發(fā)領(lǐng)域。但這四個(gè)老家伙非常怪異,總是喜歡顯擺一些高深的理論,甚至有時(shí)候不說人話,十分讓人費(fèi)解。
除了最經(jīng)典的六大設(shè)計(jì)原則以外,還有一些其他的設(shè)計(jì)原則也非常重要,本文會一起列舉,不斷收集,不斷更新。
我將盡可能地解釋這些晦澀的理論,希望看完本文之后,會讓您對這些設(shè)計(jì)原則稍微加深一些理解。若有不正確的地方,懇請大家指正!
1. 單一職責(zé)原則(Single Responsibility Principle -?SRP)
永遠(yuǎn)不應(yīng)該有多于一個(gè)原因來改變某個(gè)類。
對于一個(gè)類而言,應(yīng)該僅有一個(gè)引起它變化的原因。說白了就是,不同的類具備不同的職責(zé),各施其責(zé)。這就好比一個(gè)團(tuán)隊(duì),大家分工協(xié)作,互不影響,各做各的事情。
當(dāng)我們做系統(tǒng)設(shè)計(jì)時(shí),如果發(fā)現(xiàn)有一個(gè)類擁有了兩種的職責(zé),那就問自己一個(gè)問題:可以將這個(gè)類分成兩個(gè)類嗎?如果真的有必要,那就分吧。千萬不要讓一個(gè)類干的事情太多!
2. 開放封閉原則(Open Closed Principle -?OCP)
軟件實(shí)體,如:類、模塊與函數(shù),對于擴(kuò)展應(yīng)該是開放的,但對于修改應(yīng)該是封閉的。
簡言之,對擴(kuò)展開放,對修改封閉。換句話說,可以去擴(kuò)展類,但不要去修改類。
當(dāng)需求有改動,要修改代碼了,此時(shí)您要做的是,盡量用繼承或組合的方式來擴(kuò)展類的功能,而不是直接修改類的代碼。當(dāng)然,如果能夠確保對整體架構(gòu)不會產(chǎn)生任何影響,那么也沒必要搞得那么復(fù)雜了,直接改這個(gè)類吧。
3. 里氏替換原則(Liskov Substitution Principle -?LSP)
使用基類的指針或引用的函數(shù),必須是在不知情的情況下,能夠使用派生類的對象。
父類能夠替換子類,但子類不一定能替換父類。也就是說,在代碼中可以將父類全部替換為子類,程序不會報(bào)錯(cuò),也不會在運(yùn)行時(shí)出現(xiàn)任何異常,但反過來卻不一定成立。
在繼承類時(shí),務(wù)必重寫(Override)父類中所有的方法,尤其需要注意父類的 protected 方法(它們往往是讓您重寫的),子類盡量不要暴露自己的 public 方法供外界調(diào)用。
該原則由麻省理工學(xué)院的?Barbara Liskov?女士提出,她是美國第一位獲取計(jì)算機(jī)博士學(xué)位的女性,曾經(jīng)也獲得過計(jì)算機(jī)圖靈獎。
4. 最少知識原則(Least Knowledge Principle -?LKP)
盡量減少對象之間的交互,從而減小類之間的耦合。簡言之,一定要做到:低耦合,高內(nèi)聚。
在做系統(tǒng)設(shè)計(jì)時(shí),不要讓一個(gè)類依賴于太多的其他類,需盡量減小依賴關(guān)系,否則,您死都不知道自己怎么死的。
該原則也稱為“迪米特法則(Law of Demeter)”,由?Ian Holland 提出。這個(gè)人不太愿意和陌生人說話,只和他走得最近的朋友們交流。
5. 接口隔離原則(Interface Segregation Principle -?ISP)
一個(gè)類與另一個(gè)類之間的依賴性,應(yīng)該依賴于盡可能小的接口。
不要對外暴露沒有實(shí)際意義的接口。也就是說,接口是給別人調(diào)用的,那就不要去為難別人了,盡可能保證接口的實(shí)用性吧。她好,我也好。
當(dāng)需要對外暴露接口時(shí),需要再三斟酌,如果真的沒有必要對外提供的,就刪了吧。一旦您提供了,就意味著,您將來要多做一件事情,何苦要給自己找事做呢。
6. 依賴倒置原則(Dependence Inversion Principle -?DIP)
高層模塊不應(yīng)該依賴于低層模塊,它們應(yīng)該依賴于抽象。抽象不應(yīng)該依賴于細(xì)節(jié),細(xì)節(jié)應(yīng)該依賴于抽象。
應(yīng)該面向接口編程,不應(yīng)該面向?qū)崿F(xiàn)類編程。面向?qū)崿F(xiàn)類編程,相當(dāng)于就是論事,那是正向依賴(正常人思維);面向接口編程,相當(dāng)于通過事物表象來看本質(zhì),那是反向依賴,即依賴倒置(程序員思維)。
并不是說,所有的類都要有一個(gè)對應(yīng)的接口,而是說,如果有接口,那就盡量使用接口來編程吧。
將以上六大原則的英文首字母拼在一起就是 SOLID(穩(wěn)定的),所以也稱之為 SOLID 原則。
只有滿足了這六大原則,才能設(shè)計(jì)出穩(wěn)定的軟件架構(gòu)!但它們畢竟只是原則,只是四人幫給我們的建議,有些時(shí)候我們還是要學(xué)會靈活應(yīng)變,千萬不要生搬硬套,否則只會把簡單問題復(fù)雜化,切記!
二、補(bǔ)充設(shè)計(jì)原則
1. 組合/聚合復(fù)用原則(Composition/Aggregation Reuse Principle - CARP)
當(dāng)要擴(kuò)展類的功能時(shí),優(yōu)先考慮使用組合,而不是繼承。這條原則在 23 種經(jīng)典設(shè)計(jì)模式中頻繁使用,如:代理模式、裝飾模式、適配器模式等。可見江湖地位非常之高!
2. 無環(huán)依賴原則(Acyclic Dependencies Principle - ADP)
當(dāng) A 模塊依賴于 B 模塊,B 模塊依賴于 C 模塊,C 依賴于 A 模塊,此時(shí)將出現(xiàn)循環(huán)依賴。在設(shè)計(jì)中應(yīng)該避免這個(gè)問題,可通過引入“中介者模式”解決該問題。
3. 共同封裝原則(Common Closure Principle - CCP)
應(yīng)該將易變的類放在同一個(gè)包里,將變化隔離出來。該原則是“開放-封閉原則”的延生。
4. 共同重用原則(Common Reuse Principle - CRP)
如果重用了包中的一個(gè)類,那么也就相當(dāng)于重用了包中的所有類,我們要盡可能減小包的大小。
5.?好萊塢原則(Hollywood Principle - HP)
好萊塢明星的經(jīng)紀(jì)人一般都很忙,他們不想被打擾,往往會說:Don't call me, I'll call you. 翻譯為:不要聯(lián)系我,我會聯(lián)系你。對應(yīng)于軟件設(shè)計(jì)而言,最著名的就是“控制反轉(zhuǎn)”(或稱為“依賴注入”),我們不需要在代碼中主動的創(chuàng)建對象,而是由容器幫我們來創(chuàng)建并管理這些對象。
三、其他設(shè)計(jì)原則
1. 不要重復(fù)你自己(Don't repeat yourself - DRY)
不要讓重復(fù)的代碼到處都是,要讓它們足夠的重用,所以要盡可能地封裝。
2. 保持它簡單與傻瓜(Keep it simple and stupid - KISS)
不要讓系統(tǒng)變得復(fù)雜,界面簡潔,功能實(shí)用,操作方便,要讓它足夠的簡單,足夠的傻瓜。
3. 高內(nèi)聚與低耦合(High Cohesion and Low Coupling - HCLC)
模塊內(nèi)部需要做到內(nèi)聚度高,模塊之間需要做到耦合度低。
4. 慣例優(yōu)于配置(Convention over Configuration - COC)
盡量讓慣例來減少配置,這樣才能提高開發(fā)效率,盡量做到“零配置”。很多開發(fā)框架都是這樣做的。
5. 命令查詢分離(Command Query Separation - CQS)
在定義接口時(shí),要做到哪些是命令,哪些是查詢,要將它們分離,而不要揉到一起。
6. 關(guān)注點(diǎn)分離(Separation of Concerns - SOC)
將一個(gè)復(fù)雜的問題分離為多個(gè)簡單的問題,然后逐個(gè)解決這些簡單的問題,那么這個(gè)復(fù)雜的問題就解決了。難就難在如何進(jìn)行分離。
7. 契約式設(shè)計(jì)(Design by Contract - DBC)
模塊或系統(tǒng)之間的交互,都是基于契約(接口或抽象)的,而不要依賴于具體實(shí)現(xiàn)。該原則建議我們要面向契約編程。
8. 你不需要它(You aren't gonna need it - YAGNI)
不要一開始就把系統(tǒng)設(shè)計(jì)得非常復(fù)雜,不要陷入“過度設(shè)計(jì)”的深淵。應(yīng)該讓系統(tǒng)足夠的簡單,而卻又不失擴(kuò)展性,這是其中的難點(diǎn)。
?
與50位技術(shù)專家面對面20年技術(shù)見證,附贈技術(shù)全景圖總結(jié)
- 上一篇: 光大白金不激活要注销
- 下一篇: 知识分类