JavaScript面向對象設計原則

??面向對象編程的設計原則通常指的是單一職責原則、開放封閉原則、里氏替換原則、接口隔離原則、依賴倒置原則、合成復用原則和最少知識原則。適合JS開發(fā)的設計原則包括是單一職責原則、最少知識原則和開放封閉原則。

單一職責原則

??單一職責原則(SRP)的職責被定義為“引起變化的原因”。如果有兩個動機去改寫一個方法,那么這個方法就具有兩個職責。每個職責都是變化的一個軸線,如果一個方法承擔了過多的職責,那么在需求的變遷過程中,需要改寫這個方法的可能性就越大。此時,這個方法通常是一個不穩(wěn)定的方法,修改代碼總是一件危險的事情,特別是當兩個職責耦合在一起的時候,一個職責發(fā)生變化可能會影響到其他職責的實現(xiàn),造成意想不到的破壞,這種耦合性得到的是低內聚和脆弱的設計。因此,SRP原則體現(xiàn)為:一個對象(方法)只做一件事情。

何時應該分離職責?

??SRP原則是所有原則中最簡單也是最難正確運用的原則之一。要明確的是,并不是所有的職責都應該一一分離。
??一方面,如果隨著需求的變化,有兩個職責總是同時變化,那就不必分離他們。比如在ajax請求的時候,創(chuàng)建xhr對象和發(fā)送xhr請求幾乎總是在一起的,那么創(chuàng)建xhr對象的職責和發(fā)送xhr請求的職責就沒有必要分開。
??另一方面,職責的變化軸線僅當它們確定會發(fā)生變化時才具有意義,即使兩個職責已經(jīng)被耦合在一起,但它們還沒有發(fā)生改變的征兆,那么也許沒有必要主動分離它們,在代碼需要重構的時候再進行分離也不遲。

違反SRP原則

??在人的常規(guī)思維中,總是習慣性地把一組相關的行為放到一起,如何正確地分離職責不是一件容易的事情。在實際開發(fā)中,因為種種原因違反SRP的情況并不少見。比如jQuery的attr等方法,就是明顯違反SRP原則的做法。jQuery的attr是個非常龐大的方法,既負責賦值,又負責取值,這對于jQuery的維護者來說,會帶來一些困難,但對于jQuery的用戶來說,卻簡化了用戶的使用。在方便性與穩(wěn)定性之間要有一些取舍。具體是選擇方便性還是穩(wěn)定性,并沒有標準答案,而是要取決于具體的應用環(huán)境。

SRP原則的優(yōu)缺點

??SRP原則的優(yōu)點是降低了單個類或者對象的復雜度,按照職責把對象分解成更小的粒度,這有助于代碼的復用,也有利于進行單元測試。當一個職責需要變更的時候,不會影響到其他的職責。但SRP原則也有一些缺點,最明顯的是會增加編寫代碼的復雜度。當按照職責把對象分解成更小的粒度之后,實際上也增大了這些對象之間相互聯(lián)系的難度。

最少知識原則

??最少知識原則(LKP)(也叫迪米特法則)說的是一個軟件實體應當盡可能少地與其他實體發(fā)生相互作用。這里的軟件實體是一個廣義的概念,不僅包括對象,還包括系統(tǒng)、類、模塊、函數(shù)、變量等。
??最少知識原則要求我們在設計程序時,應當盡量減少對象之間的交互。如果兩個對象之間不必彼此直接通信,那么這兩個對象就不要發(fā)生直接的相互聯(lián)系。常見的做法是引入一個第三者對象,來承擔這些對象之間的通信作用。如果一些對象需要向另一些對象發(fā)起請求,可以通過第三者對象來轉發(fā)這些請求
  最少知識原則在設計模式中體現(xiàn)得最多的地方是中介者模式和外觀模式。

??現(xiàn)在著重看看外觀模式和最少知識原則之間的關系。外觀模式的作用主要有兩點:
??1、為一組子系統(tǒng)提供一個簡單便利的訪問入口。
??2、隔離客戶與復雜子系統(tǒng)之間的聯(lián)系,客戶不用去了解子系統(tǒng)的細節(jié)。
??從第二點來,外觀模式是符合最少知識原則的。

封裝

??封裝在很大程度上表達的是數(shù)據(jù)的隱藏。一個模塊或者對象可以將內部的數(shù)據(jù)或者實現(xiàn)細節(jié)隱藏起來,只暴露必要的接口API供外界訪問。對象之間難免產(chǎn)生聯(lián)系,當一個對象必須引用另外一個對象的時候,可以讓對象只暴露必要的接口,讓對象之間的聯(lián)系限制在最小的范圍之內。同時,封裝也用來限制變量的作用域。在JS中對變量作用域的規(guī)定是:
  1、變量在全局聲明,或者在代碼的任何位置隱式申明(不用var),則該變量在全局可見;
  2、變量在函數(shù)內顯式申明(使用var),則在函數(shù)內可見。把變量的可見性限制在一個盡可能小的范圍內,這個變量對其他不相關模塊的影響就越小,變量被改寫和發(fā)生沖突的機會也越小。這也是廣義的最少知識原則的一種體現(xiàn)。

開發(fā)封閉原則

??開放封閉原則的思想是當需要改變一個程序的功能或者給這個程序增加新功能的時候,可以使用增加代碼的方式,但是不允許改動程序的源代碼。
??過多的條件分支語句是造成程序違反開放——封閉原則的一個常見原因。每當需要增加一個新的if語句時,都要被迫改動原函數(shù)。把if換成switch-case是沒有用的,這是一種換湯不換藥的做法。實際上,每當看到一大片的if或者swtich-case語句時,第一時間就應該考慮,能否利用對象的多態(tài)性來重構它們。
  遵守開放——封閉原則的規(guī)律,最明顯的就是找出程序中將要發(fā)生變化的地方,然后把變化封裝起來。通過封裝變化的方式,可以把系統(tǒng)中穩(wěn)定不變的部分和容易變化的部分隔離開來。在系統(tǒng)的演變過程中,只需要替換那些容易變化的部分,如果這些部分是已經(jīng)被封裝好的,那么替換起來也相對容易。而變化部分之外的就是穩(wěn)定的部分。在系統(tǒng)的演變過程中,穩(wěn)定的部分是不需要改變。
??在面向對象的程序設計中,開放——封閉原則(OCP)是最重要的一條原則。很多時候,一個程序具有良好的設計,往往說明它是符合開放封閉原則的。有一種說法是,設計模式就是給做的好的設計取個名字。幾乎所有的設計模式都是遵守開放封閉原則的。不管是具體的各種設計模式,還是更抽象的面向對象設計原則,比如單一職責原則、最少知識原則、依賴倒置原則等,都是為了讓程序遵守開放封閉原則而出現(xiàn)的。

開放封閉原則的相對性

??實際上,讓程序保持完全封閉是不容易做到的。就算技術上做得到,也需要花費太多的時間和精力。而且讓程序符合開放封閉原則的代價是引入更多的抽象層次,更多的抽象有可能會增大代碼的復雜度。更何況,有一些代碼是無論如何也不能完全封閉的,總會存在一些無法對其封閉的變化。
  作為程序員,可以做到的有下面兩點:
  1、挑選出最容易發(fā)生變化的地方,然后構造抽象來封閉這些變化。
  2、在不可避免發(fā)生修改的時候,盡量修改那些相對容易修改的地方。拿一個開源庫來說,修改它提供的配置文件,總比修改它的源代碼來得簡單。

參考文獻

《JavaScript設計模式與開發(fā)實踐》

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容