js 的七大原則--單一原則、開閉原則、替換原則(一)


一.前言:

js 的七大設計原則:

1.單一原則

2.開閉原則

3.里氏替換原則

4.依賴倒轉原則

5.接口隔離原則

6.合成復用原則

7.迪米爾法則

二.單一原則

1.定義:單一原則就是一個對象或者一個方法,只做一件事。

比如,目前公司的前端框架,如下圖:在src中api只是做接口層,assets里面是公共的方法,components是用來放組件的,里面的base和business分別存放的是基礎組件和業務組件,mixins是用來存放混入的東西的。store文件時用來放vuex中的東西的,style文件是用來存放樣式的。每個文件都有各自的職責,也都只負責一件事情。這就符合單一職責的。

遵循單一職責的優點:

1.可以降低類的復雜度,一個類只負責一項職責,其邏輯肯定要比負責多項職責簡單的多。

2.提高類的可讀性,提高系統的可維護性。

3.變更引起的風險降低,變更時必然的,如果單一職責原則遵守的好,當修改一個功能時,可以顯著降低對其他功能的影響。

三.開閉原則

盡量通過擴展軟件實體來解決需求變化,而不是通過修改已有的代碼來完成變化。

一個軟件產品的生命周期內,都會發生變化,既然變化是一個既定的事實,我們就應該在設計的時候,盡量的適應這些變化。以提高項目的穩定性和靈活性。

四.里氏替換原則

嚴格的定義:如果對每一個類型為T1的對象o1,都有類型為T2的對象o2,使得以T1定義的所有程序p在所有的對象o1都換成o2的時候,程序p的行為沒有變化,那么類型T2就是類型T1的子類型。

通俗的定義:所有引用基類的地方必須能透明地使用其子類的功能。

更通俗的定義:子類可以擴展父類的功能,但是不能改變父類原有的功能。

首先來看一個例子,看它是否滿足“里氏替換”的原則

//定義一個矩形類

class
Rectangle { constructor() { this.width=0; this.height=0; } setWidth(width) { this.width = width } setHeight(height) { this.height = height } getArea() { return this.width * this.height } }

//定義一個正方形類,繼承於矩形類
class Square extends Rectangle { constructor() { super(); } setWidth(width) { this.width = width; this.height = width; } setHeight(height) { this.height = height this.width = height } }
// 執行的方法 function result(rectangles) { rectangles.forEach((rectangle)
=> { rectangle.setHeight(5) rectangle.setWidth(4) let area = rectangle.getArea() console.log('area', area) }) } let rectangles = [new Rectangle(), new Rectangle(), new Square()]; result(rectangles) //結果是20 ,20, 16

在我當初看到這個代碼的時候,我的疑惑點在於為什么正方形求面積是16。其實,仔細看一下上面的代碼,我們會發現,其實他是沒有遵循“里氏替換”的原則的。因為正方形的類繼承了矩形的類,但是它在實現的時候改寫了矩形的類。這樣子,如果我們將子類替換成父類的時候,結果就是不成功的。所以,里氏替換原則包含以下4層含義:

1.子類可以實現父類的抽象方法,但是不能覆蓋父類的非抽象的方法。

2.子類可以增加自己獨有的方法

3.當子類覆蓋或者實現父類的時候,方法的前置條件(即方法的形參)要比父類方法的輸入參數更寬松。

4.當子類的方法實現父類的抽象方法時,方法的后置條件(即方法的返回值)要比父類更嚴格。

上面的例子,在正方形的類中的setHeight方法不僅僅改變了height,還改變了width,當功能擴展的時候,子類盡量不要去重寫父類的方法,而是另寫一個方法。

五.依賴倒置原則

定義:高層模塊不應該依賴於 低層模塊,二者都應該依賴其抽象;抽象不應該依賴於細節,細節應該依賴於抽象。

怎么理解上面的話呢?

類A直接依賴類B,假如要將類A改為依賴類C,則必須通過修改類A的代碼來達成。這種場景下,類A一般是高層模塊,負責復雜的業務邏輯;類B和類C是低層模塊,負責基本的原子操作;假如修改類A,會給程序帶來不必要的風險。

在這里面類A就相當於高層模塊,類B和類C就相當於低層模塊。所以現在的業務邏輯是不滿足“依賴倒置”原則的。為了滿足“依賴倒置”的原則,其實,我們應該有一個抽象類o,然后類b,類c是o的實現,然后類A通過o簡介與類B,類c 創建聯系,這樣,就大大降低了修改類A的幾率了。

依賴倒置原則基於這樣一個事實:相對於細節的多變性,抽象的東西要穩定的多。以抽象為基礎搭建起來的架構比以細節為基礎搭建起來的架構要穩定的多。在Java中,抽象指的是接口或者抽象類,細節就是具體的實現類。使用接口或者抽象類的目的是制定好規范和契約,而不去設計任何具體的操作,把展現細節的任務交給她們的實現類去完成。

六.接口隔離原則

每一個接口都是一個角色,客戶端不應該依賴於他不需要的接口。也就是說,一個類對另一個類的依賴應該建立在最小的接口上。

應該把每一個接口都細化,針對類去設計接口。如果一個接口中有 太多的方法,而對很多類來說里面的很多方法都是用不到的,那么,另外的類在實現這個接口時就要實現很多對它來說沒用的方法,浪費人力物力。對一個類來說,實現很多它都能用得上的專用接口總比讓它實現一個臃腫而又有很多它用不上的方法要來的划算。

采用接口隔離的原則,需要注意以下幾點:

1.接口盡量小,但是要有限度。對接口進行細化可以提高程序設計靈活性是不爭的事實,但是,如果過小,則會造成接口數量過多,使得設計復雜化。所以,一定要適度。

2.為依賴接口的類定制服務,只暴露給調用的類它需要的方法,它不需要的方法則隱藏起來。只有專注地為一個模塊提供定制的服務,才能建立最小的依賴關系。

3.提高內聚,減少對外交互。使接口用最少的方法去完成最多的事情。

4.運用接口隔離原則,一定要適度。接口設計過大或過小都不好。

七.合成/聚合復用原則

聚合表示一種弱的“擁有”的關系,體現的是A對象可以包含B對象,但是B對象不是A對象的一部分;合成則是一種強的“擁有”的關系,體現了嚴格的部分和整體的關系,部分和整體的生命周期一樣。

優先使用對象的合成/聚合將有助於保持每個類的封裝,並被幾種在單個任務上。這樣類和類繼承層次會保持較小的規模,並且不太可能增長到不可控制的龐然大物上。

八.迪米特法則

也叫最小知識原則,一個對象應該對其他對象有盡可能少的了解。

總結:

單一職責原則告訴我們實現類要職責單一;里氏替換原則告訴我們不要破壞繼承體系;依賴倒置原則告訴我們要面向接口編程;接口隔離原則告訴我們在設計接口的時候要精簡單一;迪米特法則告訴我們要降低耦合。而開閉原則是總綱,他告訴我們要對擴展開放,對修改關閉。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM