成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

如何寫出優雅的 JS 代碼?使用 SOLID 原則

開發 前端
設計模式的六個原則的首字母聯合起來(兩個 L 算做一個)就是 SOLID (solid,穩定的),其代表的含義就是這六個原則結合使用的好處:建立穩定、靈活、健壯的設計。下面我們來分別看一下這六大設計原則。

本文轉載自微信公眾號「大遷世界」,轉載本文請聯系大遷世界公眾號。

設計模式的六大原則有:

  • Single Responsibility Principle:單一職責原則
  • Open Closed Principle:開閉原則
  • Liskov Substitution Principle:里氏替換原則
  • Law of Demeter:迪米特法則
  • Interface Segregation Principle:接口隔離原則
  • Dependence Inversion Principle:依賴倒置原則

把這六個原則的首字母聯合起來(兩個 L 算做一個)就是 SOLID (solid,穩定的),其代表的含義就是這六個原則結合使用的好處:建立穩定、靈活、健壯的設計。下面我們來分別看一下這六大設計原則。

[[326031]]

單一職責原則(SRP)

單一功能原則 :單一功能原則 認為對象應該僅具有一種單一功能的概念。

換句話說就是讓一個類只做一種類型責任,當這個類需要承擔其他類型的責任的時候,就需要分解這個類。在所有的SOLID原則中,這是大多數開發人員感到最能完全理解的一條。嚴格來說,這也可能是違反最頻繁的一條原則了。單一責任原則可以看作是低耦合、高內聚在面向對象原則上的引申,將責任定義為引起變化的原因,以提高內聚性來減少引起變化的原因。責任過多,可能引起它變化的原因就越多,這將導致責任依賴,相互之間就產生影響,從而極大的損傷其內聚性和耦合度。單一責任,通常意味著單一的功能,因此不要為一個模塊實 現過多的功能點,以保證實體只有一個引起它變化的原因。

「不好的寫法」

  1. class UserSettings { 
  2.   constructor(user) { 
  3.     this.user = user; 
  4.   } 
  5.  
  6.   changeSettings(settings) { 
  7.     if (this.verifyCredentials()) { 
  8.       // ... 
  9.     } 
  10.   } 
  11.  
  12.   verifyCredentials() { 
  13.     // ... 
  14.   } 

「好的寫法」

  1. class UserAuth { 
  2.   constructor(user) { 
  3.     this.user = user; 
  4.   } 
  5.  
  6.   verifyCredentials() { 
  7.     // ... 
  8.   } 
  9.  
  10. class UserSettings { 
  11.   constructor(user) { 
  12.     this.user = user; 
  13.     this.auth = new UserAuth(user); 
  14.   } 
  15.  
  16.   changeSettings(settings) { 
  17.     if (this.auth.verifyCredentials()) { 
  18.       // ... 
  19.     } 
  20.   } 

開放閉合原則 (OCP)

軟件實體應該是可擴展,而不可修改的。也就是說,對擴展是開放的,而對修改是封閉的。這個原則是諸多面向對象編程原則中最抽象、最難理解的一個。

  • 通過增加代碼來擴展功能,而不是修改已經存在的代碼。
  • 若客戶模塊和服務模塊遵循同一個接口來設計,則客戶模塊可以不關心服務模塊的類型,服務模塊可以方便擴展服務(代碼)。
  • OCP支持替換的服務,而不用修改客戶模塊。

說大白話就是:你不是要變化嗎?,那么我就讓你繼承實現一個對象,用一個接口來抽象你的職責,你變化越多,繼承實現的子類就越多。

「不好的寫法」

  1. class AjaxAdapter extends Adapter { 
  2.   constructor() { 
  3.     super(); 
  4.     this.name = "ajaxAdapter"
  5.   } 
  6.  
  7. class NodeAdapter extends Adapter { 
  8.   constructor() { 
  9.     super(); 
  10.     this.name = "nodeAdapter"
  11.   } 
  12.  
  13. class HttpRequester { 
  14.   constructor(adapter) { 
  15.     this.adapter = adapter; 
  16.   } 
  17.  
  18.   fetch(url) { 
  19.     if (this.adapter.name === "ajaxAdapter") { 
  20.       return makeAjaxCall(url).then(response => { 
  21.         // transform response and return 
  22.       }); 
  23.     } else if (this.adapter.name === "nodeAdapter") { 
  24.       return makeHttpCall(url).then(response => { 
  25.         // transform response and return 
  26.       }); 
  27.     } 
  28.   } 
  29.  
  30. function makeAjaxCall(url) { 
  31.   // request and return promise 
  32.  
  33. function makeHttpCall(url) { 
  34.   // request and return promise 

「好的寫法」

  1. class AjaxAdapter extends Adapter { 
  2.   constructor() { 
  3.     super(); 
  4.     this.name = "ajaxAdapter"
  5.   } 
  6.  
  7.   request(url) { 
  8.     // request and return promise 
  9.   } 
  10.  
  11. class NodeAdapter extends Adapter { 
  12.   constructor() { 
  13.     super(); 
  14.     this.name = "nodeAdapter"
  15.   } 
  16.  
  17.   request(url) { 
  18.     // request and return promise 
  19.   } 
  20.  
  21. class HttpRequester { 
  22.   constructor(adapter) { 
  23.     this.adapter = adapter; 
  24.   } 
  25.  
  26.   fetch(url) { 
  27.     return this.adapter.request(url).then(response => { 
  28.       // transform response and return 
  29.     }); 
  30.   } 

里氏替換原則(LSP)

里氏替換原則 :里氏替換原則 認為“程序中的對象應該是可以在不改變程序正確性的前提下被它的子類所替換的”的概念。

LSP則給了我們一個判斷和設計類之間關系的基準:需不需 要繼承,以及怎樣設計繼承關系。

當一個子類的實例應該能夠替換任何其超類的實例時,它們之間才具有is-A關系。繼承對于「OCP」,就相當于多態性對于里氏替換原則。子類可以代替基類,客戶使用基類,他們不需要知道派生類所做的事情。這是一個針對行為職責可替代的原則,如果S是T的子類型,那么S對象就應該在不改變任何抽象屬性情況下替換所有T對象。

客戶模塊不應關心服務模塊的是如何工作的;同樣的接口模塊之間,可以在不知道服務模塊代碼的情況下,進行替換。即接口或父類出現的地方,實現接口的類或子類可以代入。

「不好的寫法」

  1. class Rectangle { 
  2.   constructor() { 
  3.     this.width = 0
  4.     this.height = 0
  5.   } 
  6.  
  7.   setColor(color) { 
  8.     // ... 
  9.   } 
  10.  
  11.   render(area) { 
  12.     // ... 
  13.   } 
  14.  
  15.   setWidth(width) { 
  16.     this.width = width; 
  17.   } 
  18.  
  19.   setHeight(height) { 
  20.     this.height = height; 
  21.   } 
  22.  
  23.   getArea() { 
  24.     return this.width * this.height; 
  25.   } 
  26.  
  27. class Square extends Rectangle { 
  28.   setWidth(width) { 
  29.     this.width = width; 
  30.     this.height = width
  31.   } 
  32.  
  33.   setHeight(height) { 
  34.     this.width = height
  35.     this.height = height; 
  36.   } 
  37.  
  38. function renderLargeRectangles(rectangles) { 
  39.   rectangles.forEach(rectangle => { 
  40.     rectangle.setWidth(4); 
  41.     rectangle.setHeight(5); 
  42.     const area = rectangle.getArea(); // BAD: Returns 25 for Square. Should be 20. 
  43.     rectangle.render(area); 
  44.   }); 
  45.  
  46. const rectangles = [new Rectangle(), new Rectangle(), new Square()]; 
  47. renderLargeRectangles(rectangles); 

「好的寫法」

  1. class Shape { 
  2.   setColor(color) { 
  3.     // ... 
  4.   } 
  5.  
  6.   render(area) { 
  7.     // ... 
  8.   } 
  9.  
  10. class Rectangle extends Shape { 
  11.   constructor(width, height) { 
  12.     super(); 
  13.     this.width = width; 
  14.     this.height = height; 
  15.   } 
  16.  
  17.   getArea() { 
  18.     return this.width * this.height; 
  19.   } 
  20.  
  21. class Square extends Shape { 
  22.   constructor(length) { 
  23.     super(); 
  24.     this.length = length; 
  25.   } 
  26.  
  27.   getArea() { 
  28.     return this.length * this.length; 
  29.   } 
  30.  
  31. function renderLargeShapes(shapes) { 
  32.   shapes.forEach(shape => { 
  33.     const area = shape.getArea(); 
  34.     shape.render(area); 
  35.   }); 
  36.  
  37. const shapes = [new Rectangle(4, 5), new Rectangle(4, 5), new Square(5)]; 
  38. renderLargeShapes(shapes); 

接口隔離原則(ISP)

接口隔離原則 :接口隔離原則 認為“多個特定客戶端接口要好于一個寬泛用途的接口”的概念。

不能強迫用戶去依賴那些他們不使用的接口。換句話說,使用多個專門的接口比使用單一的總接口總要好。

這個原則起源于施樂公司,他們需要建立了一個新的打印機系統,可以執行諸如裝訂的印刷品一套,傳真多種任務。此系統軟件創建從底層開始編制,并實現了這些 任務功能,但是不斷增長的軟件功能卻使軟件本身越來越難適應變化和維護。每一次改變,即使是最小的變化,有人可能需要近一個小時的重新編譯和重新部署。這 是幾乎不可能再繼續發展,所以他們聘請羅伯特Robert幫助他們。他們首先設計了一個主要類Job,幾乎能夠用于實現所有任務功能。只要調用Job類的 一個方法就可以實現一個功能,Job類就變動非常大,是一個胖模型啊,對于客戶端如果只需要一個打印功能,但是其他無關打印的方法功能也和其耦合,ISP 原則建議在客戶端和Job類之間增加一個接口層,對于不同功能有不同接口,比如打印功能就是Print接口,然后將大的Job類切分為繼承不同接口的子 類,這樣有一個Print Job類,等等。

「不好的寫法」

  1. class DOMTraverser { 
  2.   constructor(settings) { 
  3.     this.settings = settings; 
  4.     this.setup(); 
  5.   } 
  6.  
  7.   setup() { 
  8.     thisthis.rootNode = this.settings.rootNode; 
  9.     this.animationModule.setup(); 
  10.   } 
  11.  
  12.   traverse() { 
  13.     // ... 
  14.   } 
  15.  
  16. const $ = new DOMTraverser({ 
  17.   rootNode: document.getElementsByTagName("body"), 
  18.   animationModule() {} // Most of the time, we won't need to animate when traversing. 
  19.   // ... 
  20. }); 

「好的寫法」

  1. class DOMTraverser { 
  2.   constructor(settings) { 
  3.     this.settings = settings; 
  4.     this.options = settings.options; 
  5.     this.setup(); 
  6.   } 
  7.  
  8.   setup() { 
  9.     thisthis.rootNode = this.settings.rootNode; 
  10.     this.setupOptions(); 
  11.   } 
  12.  
  13.   setupOptions() { 
  14.     if (this.options.animationModule) { 
  15.       // ... 
  16.     } 
  17.   } 
  18.  
  19.   traverse() { 
  20.     // ... 
  21.   } 
  22.  
  23. const $ = new DOMTraverser({ 
  24.   rootNode: document.getElementsByTagName("body"), 
  25.   options: { 
  26.     animationModule() {} 
  27.   } 
  28. }); 

依賴倒置原則(DIP)

依賴倒置原則:依賴倒置原則 認為一個方法應該遵從“依賴于抽象而不是一個實例” 的概念。依賴注入是該原則的一種實現方式。

依賴倒置原則(Dependency Inversion Principle,DIP)規定:代碼應當取決于抽象概念,而不是具體實現。

  • 高層模塊不要依賴低層模塊
  • 高層和低層模塊都要依賴于抽象;
  • 抽象不要依賴于具體實現
  • 具體實現要依賴于抽象
  • 抽象和接口使模塊之間的依賴分離

類可能依賴于其他類來執行其工作。但是,它們不應當依賴于該類的特定具體實現,而應當是它的抽象。這個原則實在是太重要了,社會的分工化,標準化都 是這個設計原則的體現。顯然,這一概念會大大提高系統的靈活性。如果類只關心它們用于支持特定契約而不是特定類型的組件,就可以快速而輕松地修改這些低級 服務的功能,同時最大限度地降低對系統其余部分的影響。

「不好的寫法」

  1. class InventoryRequester { 
  2.   constructor() { 
  3.     this.REQ_METHODS = ["HTTP"]; 
  4.   } 
  5.  
  6.   requestItem(item) { 
  7.     // ... 
  8.   } 
  9.  
  10. class InventoryTracker { 
  11.   constructor(items) { 
  12.     this.items = items; 
  13.  
  14.     // BAD: We have created a dependency on a specific request implementation. 
  15.     // We should just have requestItems depend on a request method: `request` 
  16.     this.requester = new InventoryRequester(); 
  17.   } 
  18.  
  19.   requestItems() { 
  20.     this.items.forEach(item => { 
  21.       this.requester.requestItem(item); 
  22.     }); 
  23.   } 
  24.  
  25. const inventoryTracker = new InventoryTracker(["apples", "bananas"]); 
  26. inventoryTracker.requestItems(); 

「好的寫法」

  1. class InventoryTracker { 
  2.   constructor(items, requester) { 
  3.     this.items = items; 
  4.     this.requester = requester; 
  5.   } 
  6.  
  7.   requestItems() { 
  8.     this.items.forEach(item => { 
  9.       this.requester.requestItem(item); 
  10.     }); 
  11.   } 
  12.  
  13. class InventoryRequesterV1 { 
  14.   constructor() { 
  15.     this.REQ_METHODS = ["HTTP"]; 
  16.   } 
  17.  
  18.   requestItem(item) { 
  19.     // ... 
  20.   } 
  21.  
  22. class InventoryRequesterV2 { 
  23.   constructor() { 
  24.     this.REQ_METHODS = ["WS"]; 
  25.   } 
  26.  
  27.   requestItem(item) { 
  28.     // ... 
  29.   } 
  30. const inventoryTracker = new InventoryTracker( 
  31.   ["apples", "bananas"], 
  32.   new InventoryRequesterV2() 
  33. ); 
  34. inventoryTracker.requestItems(); 

 

責任編輯:趙寧寧 來源: 大遷世界
相關推薦

2021-01-04 07:57:07

C++工具代碼

2019-09-20 15:47:24

代碼JavaScript副作用

2022-03-11 12:14:43

CSS代碼前端

2020-05-08 14:45:00

JS代碼變量

2021-12-07 08:16:34

React 前端 組件

2020-07-15 08:17:16

代碼

2020-05-11 15:23:58

CQRS代碼命令

2013-06-07 14:00:23

代碼維護

2021-09-01 08:55:20

JavaScript代碼開發

2021-11-30 10:20:24

JavaScript代碼前端

2022-02-08 19:33:13

技巧代碼格式

2022-02-17 10:05:21

CSS代碼前端

2020-12-19 10:45:08

Python代碼開發

2020-05-19 15:00:26

Bug代碼語言

2021-12-13 14:37:37

React組件前端

2017-10-24 15:28:27

PHP代碼簡潔SOLID原則

2022-09-27 09:21:34

SOLID開閉原則Go

2022-10-24 08:10:21

SQL代碼業務

2015-09-28 10:49:59

代碼程序員

2019-06-24 10:26:15

代碼程序注釋
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 青青久在线视频 | 亚洲一区二区三区久久 | 6080亚洲精品一区二区 | www亚洲精品| 国产精品久久久久久婷婷天堂 | 日韩精品久久久久久 | 中文字幕不卡在线88 | 日本成人在线免费视频 | 国产精品视频导航 | 亚洲美女在线一区 | 永久精品| 日本精品在线播放 | 国产精品一区二区视频 | 亚洲精品视频一区 | 精品美女在线观看 | 国产亚洲精品久久久久动 | 在线国产中文字幕 | 亚洲视频在线一区 | 日韩在线精品 | 国产99久久 | 欧美国产日韩在线 | 国产主播第一页 | 成人毛片视频免费 | 99久久精品一区二区毛片吞精 | av毛片在线播放 | 午夜在线影院 | 另类视频区 | 51ⅴ精品国产91久久久久久 | 日韩在线播放av | 青青草原精品99久久精品66 | 天天插天天操 | 手机在线观看av | av中文字幕在线播放 | 午夜精品三区 | 国产特级毛片aaaaaa | 国产欧美日韩二区 | 伊人久久免费 | a视频在线观看 | 黄网站免费在线观看 | 91黄在线观看 | 久久久国产精品网站 |