系統設計筆記 - 軟體服務

更新於 發佈於 閱讀時間約 9 分鐘

English version:

英文版在 hackmd

本文包涵:

  • 物件導向的 SOLID 設計原則
  • 常見系統設計模式




物件導向的 SOLID 設計原則




以物件導向 (Object-oriented programming, OOP)設計程式時,常遵循 SOLID 原則:

  • S: 單一職責原則 (Single responsibility principle):一模組一功能

每個模組 (module)或類別 (class)只做一件事,利於維護與測試

例如:處理登入模組,不該出現結帳功能 (白話:菜刀不兼鍋鏟職)

  • O: 開放封閉原則 (Open-closed principle):新需求新模組

程式碼應對「擴展」開放,對「修改」封閉

例如:想增加登入驗證,應「另建模組」,而非「直些修改舊模組」

  • L: 里氏替換原則 (Liskov substitution principle):子類別替代父類別,程式功能應不變

後代需具備祖先的所有特徵

例如:卡車屬於車,但車不一定是卡車 (卡車有輪胎、引擎等一切車子應有的組件,但「車」不只有卡車一種)

若你想開卡車去旅行,它當然能勝任 (旅遊品質是另一回事)

敞篷車、轎車、卡車都能稱作車,所以都能代步 (功能不變)

敞篷車、轎車、卡車都能稱作車,所以都能代步 (功能不變)

  • I: 介面隔離原則 (Interface segregation principle):不相關的功能就丟掉

不應強迫用戶實作不會用到的功能

例如:我只想 掃描 文件,使用 印表機 介面時,就不該強迫我使用 列印 功能

  • D: 依賴反轉原則 (Dependency inversion principle):改動低階模組不應影響高階者

高階模組不依賴低階模組,而應依賴抽象 (Abstraction),低階模組實作抽象

例如:電視遙控器 (低階)壞了,只需要再買一個,不用連電視 (高階)都換掉

因為電視不依賴遙控器,兩者依賴特定訊號協定 (抽象)


SOLID 只是指導原則,設計仍保有高度彈性

有基本概念後,就來看看常見的設計模式吧!



常見設計模式



先看統整再細說:

常見設計模式總覽

常見設計模式總覽

製表人:我自己


原型 (Prototype pattern)

先做出樣品,再靠複製來生產物件 (樣品 = 原型 = 模板)

  • 好處是:
    • 效率高

做過報告就知道,複製貼上比從頭打字快多了

    • 容易管理

想更新產品,只需修改模板

  • 範例:
    • Ctrl + CCtrl + V

當然不會這麼爛XD

    • 「用履歷模板」就是個常見案例,因為「複製」了模板,並對其進行修改


原型 (Prototype):套模生產

原型 (Prototype):套模生產

圖源:又是我


單例 (Singleton)

一類別 (class)一實例 (instance),並提供全域存取點

  • 優點:
    • 資源共享

全域存取點共用,即同個資源池大家分

    • 實例化效率高

實例化 (instantiation)時,物件才取得資源。所以若只需實例化一次,就不需要不斷獲取資源 (想像不斷開關冷氣 vs 開著冷氣,前者更耗電)

    • 管理方便

所有人 (或物件)都需從全域存取點獲得服務,則只需管理該存取點,不必為每個終端 (使用者/物件)個別服務

  • 範例:
    • 資料庫連線池 (connection pool)

這是個經典案例,若每個用戶訪問時,都需取得資料庫連線、用完再關閉,會很耗資源

反之,先取得一堆連線 (i.e. 連線「池」),使用者訪問時分配一個給他,用完再丟回池中,後者較省資源

    • 日誌管理系統 (Log system)

電腦只需一個日誌管理員,處理各種系統日誌

    • 設定檔管理員

各程式可有獨立設定檔,但讀取可用同個管理員

    • 政府機關

這應該最好理解。不會因為你我都要辦護照,政府就生出兩個外交部。

「政府」即為類別 (class),「外交部實體」便是實例 (instance)

  • 然而,單例有些缺點:
    • 違背 SOLID 的「單一職責原則 (Single responsibility principle)」
    • 高耦合性 (所有東西都掛在一起)

→ 不利單元測試 (unit test)

→ 修改局部程式碼,可能影響其他功能 (牽一髮動全身)

    • 全域變數污染 (global variable corruption)

全域存取點即為全域變數

    • Multi-Thread(多執行緒,亦稱多線程) 問題

若程式沒特別處理,每個執行緒都會產生實例

→ 可藉雙重檢查鎖定 (Double-Checked Locking Pattern,又稱「鎖暗示 (lock hint)」)解決 --- 非本文重點,故不在此贅述


單例模式 (Singleton):一類別一實例,開給全域存取

單例模式 (Singleton):一類別一實例,開給全域存取

圖源:還是我


工廠模式 (Factory Pattern)

製程與使用分離,i.e. 終端使用者毋需瞭解生產過程,出張嘴下單就好

  • 工廠的功能便是製造產品,此「產品」即為物件 (object)
  • 靠抽象 (abstraction)隔離製程
  • 使用者只需實例化物件,至於物件怎麼產出的,不必在乎 (通常也無法得知)
  • 優點:
    • 高靈活性

生產新品時,不必修改上下游程式碼

    • 易維護

工廠程式碼改不到,所以有問題一定是你的問題

    • 乾淨程式碼 (Code clarity)
  • 範例:
    • 做披薩

還記得上次訂披薩的流程嗎?看菜單 → 下單 → 取貨 → 享用

裡面可有個步驟,需要知道披薩製作過程?

除非你是廚師,否則一般人吃 100 次披薩,也不會掌握製作細節

      • 披薩餐廳就是工廠
      • 客人使用者
      • 披薩物件
    • 汽車工廠

同理,買車時僅需選輛買得起、好看、實用的車,我哪管車怎麼蹦出來的?

      • 工廠,嗯,就是工廠
      • 買家使用者
      • 汽車物件


抽象工廠 (Abstract Factory Pattern)

造工廠的藍圖,亦即工廠的工廠

  • 製作相關工廠前,不須指定具體類別 (class)
  • 關係:抽象工廠
    • 工廠
      • 物件
  • 範例:
    • 圖形化介面設計藍圖 → 抽象工廠
    • 給 Windows 的圖形化介面 → 工廠
      • 介面上的按鈕 → 物件
    • 給 Mac 的圖形化介面 → 工廠
      • 介面上的按鈕 → 物件


製造者模式 (Builder Pattern)

製程各步驟拆開,由不同製造者 (builder)負責

  • 作法:一步驟一製造者,製造者僅負責份內工作
  • 好處:
    • 解決複雜問題

大工程拆成小任務,自然容易許多

    • 避免跨度建構函式 (telescoping constructors)

有種情況是,一個類別 (class)為了接不同數量的參數 (parameter),而建立多個建構函式 (constructors),屬於一種反面模式 (anti-pattern),設計上應避免


製造者模式 (Builder pattern):拆分製造程序,各步驟由一個製造者負責

製造者模式 (Builder pattern):拆分製造程序,各步驟由一個製造者負責

圖源:仍是我How old am I? 怎麼老是我


依賴性注入 (Dependency Injection Pattern)

模組 (module)或類別 (class)應外包「所需」功能,而非自產自銷

  • 名詞解釋:
    • 依賴性 (Dependency):做某件事所需的東西

引擎跑 → 依賴引擎

    • 注入 (Injection):從外部給予某物

為手機「裝」電池,而非把電池做在手機上,如同現代無良手機品牌們

→ 將電池注入手機

  • 優點:
    • 低耦合度 (loose coupling)
    • 高靈活性 (Flexibility)
    • 容易測試
    • 乾淨程式碼 (clean code)


依賴性注入 (Dependency Injection Pattern):外包功能,而非自產自銷

依賴性注入 (Dependency Injection Pattern):外包功能,而非自產自銷

圖源:當然,只會是我


最後,來看看軟體服務常用的設計形式




軟體服務設計模式




三層式架構 (3-tier architecture)

服務拆三層:使用者 - 伺服器 - 資料庫


3層式架構 (3-tier architercture):用戶端 - 伺服器端 - 資料庫端

3層式架構 (3-tier architercture):用戶端 - 伺服器端 - 資料庫端

圖源:不是我還會是誰?

  • 哪三層?
    • 展示層 (presentation tier):顯示給使用者的門面 (前端)
    • 商業邏輯層 (business logic tier):處理核心要務 (伺服器後端)
    • 資料存取層 (Data access tier):資料取用、存儲 (資料庫)
  • 好處?
    • 關注點分離 (Separation of Concerns) → 更好維護
    • 高可擴展性 (Scalability)
    • 安全性高
    • 可重用性
    • 解耦 (Decoupling)


既然已拆成三層,就能依此結構延伸出:

  • MVC
  • MVP
  • MVVM


MVC

模型-視圖-控制器 (Model-View-Controller)

  • 模型 (Model):商業邏輯處理
  • 視圖 (View):用戶顯示模組
  • 控制器 (Controller):業務分派


MVP

模型-視圖-展示器 (Model-View-Presenter)

  • 模型 (Model):商業邏輯處理
  • 視圖 (View):用戶顯示模組
  • 展示器 (Presenter):處理資料並送至視圖


MVVM

模型-視圖-視圖模型 (Model-View-ViewModel)

這東西還真拗口

  • 模型 (Model):商業邏輯處理
  • 視圖 (View):用戶顯示模組
  • 視圖模型 (ViewModel):處理資料,並轉成視圖用格式
    • 繫結模型與視圖
    • 在此改資料可影響視圖

可獨立做單元測試 (unit test),GUI 介面非必要


有點混亂了嗎?

想像你進入咖啡廳,看著菜單選品項:菜單就是視圖 (view)

  • 如果用平板點餐,平板的程式交辦煮咖啡、送餐,則:平板便是控制器 (controller)
  • 點餐後,平板預先顯示咖啡完成畫面:平板展示器 (Presenter)
  • 若是服務生來點餐,點完再去操作咖啡機:服務生即為視圖模型 (ViewModel)


最後來個統整:

MVC、MVP、MVVM 統整

MVC、MVP、MVVM 統整

製表人:我自己

內容如有錯誤,歡迎交流指教




更瞭解系統設計了吧?

感謝您浪費時間撥冗閱讀,咱們下篇見!



avatar-img
1會員
6內容數
技術文章、文學抒發、低門檻創意實作教學,想收到通知歡迎加入
留言
avatar-img
留言分享你的想法!

































































你可能也想看
Google News 追蹤
※ 工廠模式 定義: 工廠模式是一種實現了「工廠」概念的物件導向設計模式。它提供一個通用的工廠介面,將創建instance(實例)的程式碼交由子類別各自實現,並根據需求去動態地生成相應的物件。這種模式將物件的創建邏輯與使用邏輯分開,使程式碼更容易維護和擴展。 特點: 具有高度標準化和同質性的
※ 單例模式介紹 ※ 定義:單例模式是一種設計模式,確保一個class(類)只有一個實例,並提供一個存取它的全域存取點。無論如何取值,皆只對這個實例取值。 ※ 目的:保證一個類別只會產生一個物件,而且提供存取該物件的統一方法。 ※ 講解:單例模式確保一個類無論怎麼 new 或 get,都只能拿
Thumbnail
樣板模式的定義極為簡單,卻是大型系統程式、WEB/APP應用框架的設計核心,完美展現設計模式的價值: 簡單、高效、強大。
Thumbnail
本書介紹了戰略設計、管理領域複雜度、實際應用領域驅動設計等主題。透過對核心子領域、支持子領域、限界上下文等概念的探討,提供了領域驅動設計的相關知識。這篇文章中還涉及了微服務、事件驅動架構和資料網格等相關主題,提供了設計系統和應用領域驅動設計的指導。
Thumbnail
觀察者模式透過主題訂閱/訊息通知的機制,極度增強系統的可擴展性、靈活性以及降低組件間的耦合度。概念直觀簡單,是非常實用的設計模式。
Thumbnail
代理模式通過封裝原始對象來實現對該對象的控制和管理,同時不改變原始對象的行為或客戶端與該對象互動的方式,以此介入或增強對該對象的訪問和操作。
Thumbnail
列出一套完整的程式 程式設計有許多種方法,不過通常會先列出清單的再逐一執行,這樣會加快程式設計的速度。設計通常會採取順推的辦法。所以順推的程式設計方式就是經歷觀念溝通、系統分析、資料統合、權限管理、頻率與時間、後台管理、畫面設計等等階段後,將框架設計完了以後,先列出一套完整的程式,將所有使用者都確
Thumbnail
程式設計中不可或缺的一部分 介面是使用者與程式互動的媒介,因此介面的設計會影響使用者的體驗和感受。一個清晰明白、易懂的介面,可以讓使用者輕鬆地使用程式,並獲得良好的使用體驗。 需要與程式設計師密切溝通 設計師需要了解程式的功能和需求,並根據使用者的習慣和需求進行設計。設計師和程式設計師之間的溝
Thumbnail
替產業做設計 有人要我談程式設計,那我就稍微談一下。我從事的大都是產業的工作,所以我們也從如何替產業做設計來談起。基本上,每個產業都會有自己的作業流程,大同小異。但是基礎來做都是一樣的,都會有客戶、物料、產品、供應商、員工等資料。不同的是,由於企業型態的不同,他們每個人有不同的作業流程。這個作業流
※ 工廠模式 定義: 工廠模式是一種實現了「工廠」概念的物件導向設計模式。它提供一個通用的工廠介面,將創建instance(實例)的程式碼交由子類別各自實現,並根據需求去動態地生成相應的物件。這種模式將物件的創建邏輯與使用邏輯分開,使程式碼更容易維護和擴展。 特點: 具有高度標準化和同質性的
※ 單例模式介紹 ※ 定義:單例模式是一種設計模式,確保一個class(類)只有一個實例,並提供一個存取它的全域存取點。無論如何取值,皆只對這個實例取值。 ※ 目的:保證一個類別只會產生一個物件,而且提供存取該物件的統一方法。 ※ 講解:單例模式確保一個類無論怎麼 new 或 get,都只能拿
Thumbnail
樣板模式的定義極為簡單,卻是大型系統程式、WEB/APP應用框架的設計核心,完美展現設計模式的價值: 簡單、高效、強大。
Thumbnail
本書介紹了戰略設計、管理領域複雜度、實際應用領域驅動設計等主題。透過對核心子領域、支持子領域、限界上下文等概念的探討,提供了領域驅動設計的相關知識。這篇文章中還涉及了微服務、事件驅動架構和資料網格等相關主題,提供了設計系統和應用領域驅動設計的指導。
Thumbnail
觀察者模式透過主題訂閱/訊息通知的機制,極度增強系統的可擴展性、靈活性以及降低組件間的耦合度。概念直觀簡單,是非常實用的設計模式。
Thumbnail
代理模式通過封裝原始對象來實現對該對象的控制和管理,同時不改變原始對象的行為或客戶端與該對象互動的方式,以此介入或增強對該對象的訪問和操作。
Thumbnail
列出一套完整的程式 程式設計有許多種方法,不過通常會先列出清單的再逐一執行,這樣會加快程式設計的速度。設計通常會採取順推的辦法。所以順推的程式設計方式就是經歷觀念溝通、系統分析、資料統合、權限管理、頻率與時間、後台管理、畫面設計等等階段後,將框架設計完了以後,先列出一套完整的程式,將所有使用者都確
Thumbnail
程式設計中不可或缺的一部分 介面是使用者與程式互動的媒介,因此介面的設計會影響使用者的體驗和感受。一個清晰明白、易懂的介面,可以讓使用者輕鬆地使用程式,並獲得良好的使用體驗。 需要與程式設計師密切溝通 設計師需要了解程式的功能和需求,並根據使用者的習慣和需求進行設計。設計師和程式設計師之間的溝
Thumbnail
替產業做設計 有人要我談程式設計,那我就稍微談一下。我從事的大都是產業的工作,所以我們也從如何替產業做設計來談起。基本上,每個產業都會有自己的作業流程,大同小異。但是基礎來做都是一樣的,都會有客戶、物料、產品、供應商、員工等資料。不同的是,由於企業型態的不同,他們每個人有不同的作業流程。這個作業流