(三)设计原则
設計原則
- 設計原則
- 何為“設計”
- 演示沉默是金 + 讓每個程序成為過濾器
- 設計原則
- 介紹
- 單一職責原則
- 開放封閉原則
- 李氏置換原則
- 接口隔離原則
- 依賴倒置原則
- 設計原則總結
- 舉例說明
- 從設計到模式
- 簡介 23 種設計模式
- 面試題
- 第一題
- 第二題
設計原則
- 何為“設計”?
- 五大設計原則
- 從設計到模式
- 簡介 23 種設計模式
何為“設計”
- 即按照哪一種思路或者標準來實現功能
- 功能相同,可以有不同設計方案來實現
- 伴隨著需求增加,設計的作用才能體現出來
按我的理解,通俗來說,設計(僅指編程設計)就是按照哪一種思路或者標準來實現功能。同樣的功能,不同的設計思想都能用不同的方式來實現,前期效果可能一樣,但是隨著產品功能的增加和擴展,設計的作用才會慢慢的顯示出來。
結合《UNIX/Linux 設計哲學》中提到的系統設計原則 https://github.com/wangfupeng1988/read-notes/blob/master/book/Linux-Unix%E8%AE%BE%E8%AE%A1%E6%80%9D%E6%83%B3.md 。可能有一些會跟傳統思想有區別,但是請你重視它們。
- 準則1:小即是美
- 準則2:讓每個程序只做好一件事
- 準則3:快速建立原型
- 準則4:舍棄高效率而取可移植性
- 準則5:采用純文本來存儲數據
- 準則6:充分利用軟件的杠桿效應(軟件復用)
- 準則7:使用 shell 腳本來提高杠桿效應和可移植性
- 準則8:避免強制性的用戶界面
- 準則9:讓每個程序都稱為過濾器
- 十條小準則
- 允許用戶定制環境
- 盡量使操作系統內核小而輕量化
- 使用小寫字母并盡量簡短
- 保護樹木
- 沉默是金
- 并行思考
- 各部分之和大于整體
- 尋求 90% 的解決方案
- 更壞就是更好
- 層次化思考
無論你現在能否理解以上這些準則,我都希望你每隔一段時間(如半年)都重新自省一下,看自己結合自己的工作經歷,是否又加深了這些準則的理解。
PS,這本書推薦大家買來閱讀,JD 上已經買不到正版了,其他途徑自己去找找吧。我是直接下載了電子版,然后打印出來閱讀。
設計原則和設計模式都不難理解,因為:計算機越偏向底層就越簡單、執拗、越傻(如必須使用二進制,不使用十進制),因為其本質是電子 + 數學。而越偏向于高層或者表層就要越聰明,越任性(如java語言,設計原則),因為其本質是應對變化和需求。
演示沉默是金 + 讓每個程序成為過濾器
設計原則
S O L(Liskov) I D 五大設計原則
- S - 單一職責原則
- O - 開放封閉原則
- L - 李氏置換原則
- I - 接口獨立原則
- D - 依賴導致原則
介紹
單一職責原則
- 一個程序只做好一件事
- 如果功能過于復雜就拆分開,每個部分保持獨立。
開放封閉原則
- 對修改封閉,對擴展開放
- 即要設計一種機制,當需求發生變化時,根據這種機制擴展代碼,而不是修改原有的代碼。原有代碼修改要重新測試,多人開發也很容易沖突
- 這是軟件設計的終極目標
李氏置換原則
- 子類能覆蓋父類
- 父類能出現的地方子類就能出現。
- JS 中子類繼承父類的場景較少,又不是強類型語言,因此體現較少。
接口隔離原則
- 保持接口的單一獨立,避免出現“胖接口”。
- JS中沒有接口(typescript例外),因此體現較少。
- 類似于單一職責原則,只不過前者說的比較統一,后者是單獨對接口的規定。
依賴倒置原則
- 面向接口編程,依賴于抽象而不依賴于具體。寫代碼時用到具體類時,不與具體類交互,而與具體類的上層接口交互。
- 使用方只關注接口而不關注具體類的實現
- JS中使用較少(沒有接口 & 弱類型)
只關注輸入輸出接口,內部實現不用管
設計原則總結
S O 體現較多,詳細介紹
L I D體現較少,但是要了解其用意
舉例說明
后三個原則是基于高級面向對象語言語法的(如 java),找不到太合適的例子,就先以常見的 Promise 來解釋一下前兩個原則S O。
// 加載圖片 function loadImg(src) {var promise = new Promise(function (resolve, reject) {var img = document.createElement('img')img.onload = function () {resolve(img)}img.onerror = function () {reject('圖片加載失敗')}img.src = src})return promise }var src = 'https://www.imooc.com/static/img/index/logo_new.png' var result = loadImg(src)result.then(function (img) {console.log('img.width', img.width)return img }).then(function (img) {console.log('img.height', img.height) }).catch(function (ex) {// 統一捕獲異常console.log(ex) })- 單一職責原則:每個then中的邏輯只做好一件事,如果要做多個就用多個then
- 開放封閉原則:如果這個需求要修改,那去擴展then即可,現有的邏輯不用修改,即對擴展開放、對修改封閉
這里引申兩點:
- 其實 S 和 O 是相符現成的,相互依賴
- 開放封閉原則的好處不止于此,從整個軟件開發流程看,減少現有邏輯的更改,也會減少測試的成本
從設計到模式
- 設計
- 模式
- 分開
- 從設計到模式
“設計”和“模式”應該分開看?!霸O計”即設計原則、設計思想,“模式”即一些固話了的符合設計原則的既定方式、成型的可套用的模板。先有“設計”后有“模式”,因此應該“從設計到模式”,不能將“設計模式”作為一個詞來稱呼。
這并不是故意咬文爵字。
(分開之后,你可能會有一種豁然開朗的感覺)
簡介 23 種設計模式
以下是所有 23 種設計模式。一些是前端常用且能找到經典使用場景的,一些是不常用或者找不到代表性的使用場景的。根據使用的不同,講解時也會區分優先級,重點的模式詳細講解。
- 創建型模式
- 工廠模式(工廠方法模式,抽象工廠模式,建造者模式)
- 單例模式
- 原型模式
- 結構型模式
- 適配器模式
- 裝飾器模式
- 代理模式
- 外觀模式
- 橋接模式
- 組合模式
- 享元模式
- 行為型模式
- 策略模式
- 模板方法模式
- 觀察者模式
- 迭代器模式
- 職責連模式
- 命令模式
- 備忘錄模式
- 狀態模式
- 訪問者模式
- 中介者模式
- 解釋器模式
分優先級
- 前端常用設計模式,詳講
- 前端非常用設計模式,略講
- 前端少用設計模式,介紹
接下來說兩個問題:
- 我如何講解設計模式?
- 介紹以及舉例(生活中易理解的示例)
- 畫 UML 類圖寫 demo 代碼
- 結合經典應用場景,講解該設計模式如何被使用(如果該設計模式沒有經典應用,就不講)
- 你如何學習設計模式?
- 明白每個設計的目的和道理
- 通過經典應用體會它的真正使用場景
- 自己編碼時多思考,盡量模仿
最后說明一下。雖然設計模式案例說應該基于 java 學習,因為 java 具有完善的面向對象語言編程的語法。但是現在我們限定的前提環境是前端 JS ,那就不應該再按照 java 的模式去講解設計模式,否則就是削足適履。
- JS 和 java 語法不一樣;
- 前端和 java 的應用場景也不同,如前端不會考慮并發、內存泄露
面試題
第一題
打車時,可以打專車或者快車。任何車都有車牌號和名稱
不同車價格不同,快車每公里1元,專車每公里2元
行程開始時,顯示車輛信息
行程結束時,顯示打車金額(假定行程就5公里)
要求:
畫出UML類圖
用ES6語法寫出該示例
第二題
某停車場,分3層,每層100車位
每個車位都能監控到車輛的駛入和離開
車輛進入前,顯示每層的空余車位數量
車輛進入時,攝像頭可識別車牌號和時間
車輛出來時,出口顯示器顯示車牌號和停車時長
總結