一、開閉原則解決的問題
首先不對開閉原則下定義,先看一個(gè)不遵循開閉原則的例子。
你自己組裝電腦主機(jī),首先購買各種配件,然后按照主機(jī)的組成結(jié)構(gòu)拼裝在一起,就可以愉快打游戲了。

有一天,發(fā)現(xiàn)顯卡帶不動一款大型游戲了,所以你想換一塊更好的顯卡。but,當(dāng)初買主板和顯卡時(shí),它倆的交互接口不是通用的,新買的顯卡適配不了主板。
這時(shí),你把主板換了,發(fā)現(xiàn)新主板又不適配硬盤了,最后把除了機(jī)箱電源之外的組件全部換新的,才升級完顯卡。
為了升級顯卡(擴(kuò)展功能),把大部分組件都修改了(對修改不關(guān)閉);如果最初組裝機(jī)器時(shí),各組件的接口都是通用的,那么選擇適配接口的顯卡即可完成升級。
現(xiàn)在對開閉原則下個(gè)定義,開閉原則(Open-Closed Principle, OCP):一個(gè)軟件實(shí)體應(yīng)當(dāng)對擴(kuò)展開放,對修改關(guān)閉。
二、什么是開閉原則
對擴(kuò)展開放、對修改關(guān)閉,這又是開放、又是關(guān)閉的,聽起來有些矛盾、難以理解,一個(gè)東西不可能即開放,又關(guān)閉吧?
是的,同一個(gè)東西不可能既開放、又關(guān)閉! 但是如果不是同一個(gè)東西呢?考慮上面裝機(jī)的故事,多個(gè)組件組合在一起,構(gòu)成了一臺完整的主機(jī);但是各組件又是單獨(dú)的個(gè)體,可以對他們進(jìn)行修改、擴(kuò)展。既然動詞擴(kuò)展和修改的對象不是同一個(gè),開放、關(guān)閉同時(shí)存在就成為了可能。
面向?qū)ο蟮氖澜缰幸彩侨绱耍鄠€(gè)對象通過一定的耦合,形成一個(gè)整體對外提供服務(wù)。那么什么是對修改關(guān)閉,對擴(kuò)展開放呢?
對修改關(guān)閉:參考電腦主機(jī)的組成,各個(gè)組件之間的耦合,是有一套通用、統(tǒng)一接口,這套依賴關(guān)系是不會隨著組件的不同而改變的,它是固定的,做到了“對修改關(guān)閉”。面向?qū)ο笾?,對修改關(guān)閉,意味著對象之間的依賴關(guān)系是固定的、不會隨著需求變更而修改的。對象之間的依賴架構(gòu),是不可修改的,這是對修改關(guān)閉。
對擴(kuò)展開放:世間唯一不變的就是改變,世界要向更好的方向發(fā)展。我們的需求是會不斷變化的,要想保持進(jìn)步,必須有可以改變的部分。在組裝主機(jī)中,各個(gè)組件都可以獨(dú)立升級,主機(jī)性能更加完美。面向?qū)ο笾?,對擴(kuò)展開放,意味著可以在原有的對象組織關(guān)系中,輕松增加新特性。
三、實(shí)踐開閉原則
要做到對修改關(guān)閉、構(gòu)建一個(gè)穩(wěn)固的對象依賴架構(gòu),需要高度抽象出對象的本質(zhì),依賴本質(zhì)的抽象而不是具體的對象。因?yàn)楸举|(zhì)是不會輕易改變的,通過本質(zhì)依賴構(gòu)建的結(jié)構(gòu)也不會輕易發(fā)生改變。這對軟件開發(fā)人員的抽象能力提出了很高的要求。
總結(jié)來說,就是抽象;從實(shí)踐上來說,就是依賴接口、或者抽象類,而不要依賴具體對象。這也是另一條面向?qū)ο笤O(shè)計(jì)原則所倡導(dǎo)的:面向接口編程。
要做到對擴(kuò)展開放,輕易增加新特性,需要把同類型的可變性封裝在一起。試想如果內(nèi)存的部分功能,和顯卡都做到了同一個(gè)組件上,需要升級內(nèi)存時(shí),是不是也要把顯卡也升級了?這對擴(kuò)展開放了,但是開放得不夠友好。
總結(jié)來說,就是封裝可變性;從實(shí)踐上來說,就是把同類特性封裝到一個(gè)對象中,而不要散落在各處。這也是另一條面向?qū)ο笤O(shè)計(jì)原則所倡導(dǎo)的:單一職責(zé)。
四、開閉原則在其他領(lǐng)域的應(yīng)用
不只是面向?qū)ο笤O(shè)計(jì)領(lǐng)域,其他領(lǐng)域也能找到開閉原則的影子。
redis cluster的數(shù)據(jù)分片設(shè)計(jì):
尋找key對應(yīng)的redis實(shí)例時(shí),沒有讓hash(key)直接依賴redis實(shí)例,而是抽象出一層哈希槽,讓hash(key)與哈希槽形成穩(wěn)定的依賴關(guān)系(對修改關(guān)閉)
哈希槽與redis實(shí)例的關(guān)系時(shí)可變的,可以輕易進(jìn)行水平擴(kuò)展(對擴(kuò)展開放)
