開閉原則的定義算法
開閉原則是Java世界裏最基礎的設計 原則,它指導咱們如何創建一個穩定的、靈活的系統,先來看開閉原則的定義: Software entities like classes,modules and functions should be open for extension but closed for modifications.(一個軟件實體如類、模塊和函數應該對擴展開放,對修改關閉。)數據庫
開閉原則的定義已經很是明確地告訴咱們:軟件實體應該對擴展開放,對修改關閉,其 含義是說一個軟件實體應該經過擴展來實現變化,而不是經過修改已有的代碼來實現變化。 那什麼又是軟件實體呢?軟件實體包括如下幾個部分:編程
項目或軟件產品中按照必定的邏輯規則劃分的模塊。設計模式
抽象和類。架構
方法。函數
咱們能夠把變化概括爲如下三種類型: 工具
邏輯變化 只變化一個邏輯,而不涉及其餘模塊,好比原有的一個算法是a*b+c,如今須要修改成 a*b*c,能夠經過修改原有類中的方法的方式來完成,前提條件是全部依賴或關聯類都按照 相同的邏輯處理。單元測試
子模塊變化 一個模塊變化,會對其餘的模塊產生影響,特別是一個低層次的模塊變化必然引發高層 模塊的變化,所以在經過擴展完成變化時,高層次的模塊修改是必然的學習
可見視圖變化 可見視圖是提供給客戶使用的界面,如JSP程序、Swing界面等,該部分的變化通常會引 起連鎖反應(特別是在國內作項目,作歐美的外包項目通常不會影響太大)。若是僅僅是界 面上按鈕、文字的從新排布卻是簡單,最司空見慣的是業務耦合變化,什麼意思呢?一個展 示數據的列表,按照原有的需求是6列,忽然有一天要增長1列,並且這一列要跨N張表,處 理M個邏輯才能展示出來,這樣的變化是比較恐怖的,但仍是能夠經過擴展來完成變化,這 就要看咱們原有的設計是否靈活。測試
爲何要採用開閉原則
每一個事物的誕生都有它存在的必要性,存在即合理,那開閉原則的存在也是合理的,爲 什麼這麼說呢? 首先,開閉原則很是著名,只要是作面向對象編程的,甭管是什麼語言,Java也 好,C++也好,或者是Smalltalk,在開發時都會說起開閉原則。 其次,開閉原則是最基礎的一個原則,前五章節介紹的原則都是開閉原則的具體形態, 也就是說前五個原則就是指導設計的工具和方法,而開閉原則纔是其精神領袖。換一個角度 來理解,依照Java語言的稱謂,開閉原則是抽象類,其餘五大原則是具體的實現類,開閉原 則在面向對象設計領域中的地位就相似於牛頓第必定律在力學、勾股定律在幾何學、質能方 程在狹義相對論中的地位,其地位無人能及。 最後,開閉原則是很是重要的,可經過如下幾個方面來理解其重要性。
開閉原則對測試的影響:全部已經投產的代碼都是有意義的,而且都受系統規則的約束,這樣的代碼都要經 過「千錘百煉」的測試過程,不只保證邏輯是正確的,還要保證苛刻條件(高壓力、異常、錯 誤)下不產生「有毒代碼」(Poisonous Code),所以有變化提出時,咱們就須要考慮一下, 原有的健壯代碼是否能夠不修改,僅僅經過擴展實現變化呢?不然,就須要把原有的測試過 程回籠一遍,須要進行單元測試、功能測試、集成測試甚至是驗收測試,如今雖然在大力提 倡自動化測試工具,可是仍然代替不了人工的測試工做。
開閉原則能夠提升複用性:在面向對象的設計中,全部的邏輯都是從原子邏輯組合而來的,而不是在一個類中獨立 實現一個業務邏輯。只有這樣代碼才能夠複用,粒度越小,被複用的可能性就越大。那爲什 麼要複用呢?減小代碼量,避免相同的邏輯分散在多個角落,避免往後的維護人員爲了修改 一個微小的缺陷或增長新功能而要在整個項目中處處查找相關的代碼,而後發出對開發人 員「極度失望」的感慨。那怎麼才能提升複用率呢?縮小邏輯粒度,直到一個邏輯不可再拆分 爲止。
開閉原則能夠提升可維護性:一款軟件投產後,維護人員的工做不只僅是對數據進行維護,還可能要對程序進行擴 展,維護人員最樂意作的事情就是擴展一個類,而不是修改一個類,甭管原有的代碼寫得多 麼優秀仍是多麼糟糕,讓維護人員讀懂原有的代碼,而後再修改,是一件很痛苦的事情,不 要讓他在原有的代碼海洋裏遊弋完畢後再修改,那是對維護人員的一種折磨和摧殘。
面向對象開發的要求:萬物皆對象,咱們須要把全部的事物都抽象成對象,而後針對對象進行操做,可是萬物 皆運動,有運動就有變化,有變化就要有策略去應對,怎麼快速應對呢?這就須要在設計之 初考慮到全部可能變化的因素,而後留下接口,等待「可能」轉變爲「現實」。
如何使用開閉原則;
開閉原則是一個很是虛的原則,前面5個原則是對開閉原則的具體解釋,可是開閉原則 並不侷限於這麼多,它「虛」得沒有邊界,就像「好好學習,每天向上」的口號同樣,告訴咱們 要好好學習,可是學什麼,怎麼學並無告訴咱們,須要去體會和掌握,開閉原則也是一個 口號,那咱們怎麼把這個口號應用到實際工做中呢?
抽象約束:抽象是對一組事物的通用描述,沒有具體的實現,也就表示它能夠有很是多的可能性, 能夠跟隨需求的變化而變化。所以,經過接口或抽象類能夠約束一組可能變化的行爲,而且 可以實現對擴展開放,其包含三層含義:第一,經過接口或抽象類約束擴展,對擴展進行邊 界限定,不容許出如今接口或抽象類中不存在的public方法;第二,參數類型、引用對象盡 量使用接口或者抽象類,而不是實現類;第三,抽象層儘可能保持穩定,一旦肯定即不容許修 改。
元數據(metadata)控制模塊行爲:編程是一個很苦很累的活,那怎麼才能減輕咱們的壓力呢?答案是儘可能使用元數據來控 製程序的行爲,減小重複開發。什麼是元數據?用來描述環境和數據的數據,通俗地說就是 配置參數,參數能夠從文件中得到,也能夠從數據庫中得到。
制定項目章程:在一個團隊中,創建項目章程是很是重要的,由於章程中指定了全部人員都必須遵照的 約定,對項目來講,約定優於配置。
封裝變化:對變化的封裝包含兩層含義:第一,將相同的變化封裝到一個接口或抽象類中;第二, 將不一樣的變化封裝到不一樣的接口或抽象類中,不該該有兩個不一樣的變化出如今同一個接口或 抽象類中。封裝變化,也就是受保護的變化(protected variations),找出預計有變化或不穩 定的點,咱們爲這些變化點建立穩定的接口,準確地講是封裝可能發生的變化,一旦預測到 或「第六感」發覺有變化,就能夠進行封裝,23個設計模式都是從各個不一樣的角度對變化進行 封裝的。
最佳實踐
軟件設計最大的難題就是應對需求的變化,可是紛繁複雜的需求變化又是不可預料的。 咱們要爲不可預料的事情作好準備,這自己就是一件很是痛苦的事情,可是大師們仍是給我 們提出了很是好的6大設計原則以及23個設計模式來「封裝」將來的變化,6大設計原則以下:
Single Responsibility Principle:單一職責原則
Open Closed Principle:開閉原則
Liskov Substitution Principle:里氏替換原則
Law of Demeter:迪米特法則
Interface Segregation Principle:接口隔離原則
Dependence Inversion Principle:依賴倒置原則
把這6個原則的首字母(里氏替換原則和迪米特法則的首字母重複,只取一個)聯合起 來就是SOLID(solid,穩定的),其表明的含義也就是把這6個原則結合使用的好處:創建 穩定、靈活、健壯的設計,而開閉原則又是重中之重,是最基礎的原則,是其餘5大原則的 精神領袖。咱們在使用開閉原則時要注意如下幾個問題。
開閉原則也只是一個原則:開閉原則只是精神口號,實現擁抱變化的方法很是多,並不侷限於這6大設計原則,但 是遵循這6大設計原則基本上能夠應對大多數變化。所以,咱們在項目中應儘可能採用這6大原 則,適當時候能夠進行擴充,例如經過類文件替換的方式徹底能夠解決系統中的一些缺陷。 你們在開發中比較經常使用的修復缺陷的方法就是類替換,好比一個軟件產品已經在運行中,發 現了一個缺陷,須要修正怎麼辦?若是有自動更新功能,則能夠下載一個.class文件直接覆 蓋原有的class,從新啓動應用(也不必定非要從新啓動)就能夠解決問題,也就是經過類文 件的替換方式修正了一個缺陷,固然這種方式也能夠應用到項目中,正在運行中的項目發現 須要增長一個新功能,經過修改原有實現類的方式就能夠解決這個問題,前提條件是:類必 須作到高內聚、低耦合,不然類文件的替換會引發不可預料的故障。
項目規章很是重要:若是你是一位項目經理或架構師,應儘可能讓本身的項目成員穩定,穩定後才能創建高效 的團隊文化,章程是一個團隊全部成員共同的知識結晶,也是全部成員必須遵照的約定。優 秀的章程能帶給項目帶來很是多的好處,如提升開發效率、下降缺陷率、提升團隊士氣、提 高技術成員水平,等等。
預知變化:在實踐中過程當中,架構師或項目經理一旦發現有發生變化的可能,或者變化曾經發生 過,則須要考慮現有的架構是否能夠輕鬆地實現這一變化。架構師設計一套系統不只要符合 現有的需求,還要適應可能發生的變化,這纔是一個優良的架構。 開閉原則是一個終極目標,任何人包括大師級人物都沒法百分之百作到,但朝這個方向 努力,能夠很是顯著地改善一個系統的架構,真正作到「擁抱變化」。