吃透單一職責原則,100倍效果提升程式碼質量
來源:mikechen的網際網路架構
在設計模式 7 大原則中,單一職責原則最簡單,但又較難運用。
單一職責原則的核心思想是:讓專業的人,做專業的事。
就如同醫生和護士,各有自己特定的職責,且專注於自己的職責。
單一職責原單一職責原則既是架構設計的基石,也是 Java 面試高頻必考點,非常重要。
大家好,我是mikechen。
本篇,我會透過【圖例+原始碼】結合,詳解單一職責原則。
單一職責原則是什麼
為什麼要遵循單一職責原則
單一職責原則的 UML 類圖
單一職責原則的 3 大優點
單一職責原則的實現原理及示例
PS.
Mike 已將本文內容歸納到《Java面試突擊合集》PDF,方便大家面試通關。
《Java面試突擊合集》PDF 已收錄了 600+ 道大廠面試真題,約 14 萬字,350頁。
助力面試突擊,提高面試通關率,文末自取。
單一職責原則,英文全稱 Single Responsibility Principle,又稱為單一功能原則。
單一職責原則是指一個類要職責單一,只負責一個特定的功能或任務,而不應該承擔過多的職責,使得程式碼更容易理解、維護和擴充套件。
遵循單一職責原則,每個類都專注於一個明確的職責,可以降低程式碼的複雜性,提高程式碼的可維護性。
如果一個類承擔了太多的職責,就會難以維護和修改。
一個職責的變化,可能會削弱這個類實現其他職責的能力;
當客戶端需要該物件的某一個職責時,需要將其它不需要的職責全部包含進來,這樣會導致程式碼冗餘。
單一職責原則的 UML 類圖:
在 UML 類圖中,虛線箭頭表示依賴關係,常用在方法、引數等,由依賴方指向被依賴方。
在實踐了單一職責原則的 UML 類圖中,不屬於 Employee 的兩個職責,則被分成了兩類:
FinancialApartment 類
HRApartment 類
我們再來看一個具體的示例。
假設:
一個醫院系統中,有一個名為 Doctor(醫生)的類,這個類負責管理醫生的資訊和診斷患者。
class Doctor {
private String name;
private String specialization;
public Doctor(String name, String specialization) {
this.name = name;
this.specialization = specialization;
}
public void diagnosePatient(Patient patient) {
// 實現診斷患者的邏輯
}
public void prescribeMedicine(Patient patient, String medicine) {
// 實現給患者開藥的邏輯
}
public void scheduleSurgery(Patient patient, Date date) {
// 實現安排手術的邏輯
}
// 其他與醫生資訊相關的方法和屬性
}
在這個示例中,Doctor 類不僅管理醫生的資訊,還包含了與患者的診斷、處方藥和手術安排相關的方法。
在 Doctor 類中,包含了 4 種不同的邏輯:
診斷患者;
給患者開藥;
安排手術;
其他與醫生資訊相關的方法和屬性。
這個邏輯看似沒問題,但不符合單一職責原則,因為這四種邏輯各不相同。
這樣的設計會帶來什麼影響呢?
我們想象下,如果業務發生了變化,就需要去修改當前這個類。牽一髮而動全身,這樣設計顯然不合理。
因此,我們需要對類中的不同責任進行拆分:
class Doctor {
private String name;
private String specialization;
public Doctor(String name, String specialization) {
this.name = name;
this.specialization = specialization;
}
// 醫生資訊管理的方法和屬性
// ...
}
class Patient {
// 患者資訊管理的方法和屬性
// ...
}
class MedicalStaff {
public void diagnosePatient(Doctor doctor, Patient patient) {
// 實現診斷患者的邏輯
}
public void prescribeMedicine(Doctor doctor, Patient patient, String medicine) {
// 實現給患者開藥的邏輯
}
public void scheduleSurgery(Doctor doctor, Patient patient, Date date) {
// 實現安排手術的邏輯
}
}
現在,將醫生的資訊管理、以及患者的診斷、處方藥、手術安排等功能,分別分配給不同的類:
Doctor 類:負責醫生的資訊管理;
Patient 類:負責患者的資訊管理;
MedicalStaff 類:負責醫療工作。
使用單一職責原則,將這些職責分離開來,讓每個類都有自己明確的職責,且只有一個職責。
由於職責區分,各個類的變化不會相互影響,程式碼容易理解和維護。
這裡可能有同學會問,怎麼判斷是否需要分離職責?或者說分離職責的依據是什麼?
是否需要分離職責,主要則取決於變化:
當變化發生,隻影響其中一個職責,需要拆分;
如果變化都影響到這兩個職責,則不需要拆分。
根據以上,我們總結出了單一職責原則的優點:
可以降低類的複雜性;
可以提高程式碼的可讀性、可維護性;
可以降低變更引起的風險。
示例:
在一個電商訂單處理系統中,有兩個職責:訂單管理、發貨處理。
我們可以使用單一職責原則,將這兩個職責分離開來:
// 訂單管理類負責處理訂單的建立、修改和查詢
class OrderManager {
public void createOrder(Order order) {
// 實現訂單建立邏輯
}
public void updateOrder(Order order) {
// 實現訂單修改邏輯
}
public Order getOrder(int orderId) {
// 實現訂單查詢邏輯
return null;
}
}
// 發貨處理類負責處理訂單的發貨操作
class ShippingProcessor {
public void shipOrder(Order order) {
// 實現訂單發貨邏輯
}
}
// 訂單類,包含訂單的相關資訊
class Order {
private int orderId;
private String customerName;
private String shippingAddress;
// 其他訂單資訊的成員變數和方法
public Order(int orderId, String customerName, String shippingAddress) {
this.orderId = orderId;
this.customerName = customerName;
this.shippingAddress = shippingAddress;
// 初始化其他訂單資訊
}
// 其他訂單操作的方法和屬性訪問器
}
public class Main {
public static void main(String[] args) {
OrderManager orderManager = new OrderManager();
ShippingProcessor shippingProcessor = new ShippingProcessor();
// 建立訂單
Order newOrder = new Order(1, "John Doe", "123 Main St");
orderManager.createOrder(newOrder);
// 查詢訂單
Order retrievedOrder = orderManager.getOrder(1);
// 發貨訂單
shippingProcessor.shipOrder(retrievedOrder);
}
}
在這個示例中:
OrderManager 類:負責訂單的建立、修改和查詢;
ShippingProcessor 類:負責訂單的發貨操作。
每個類都有明確的職責,且只負責一個職責,避免了不必要的複雜性和依賴關係。
本文重點介紹了單一職責原則的核心知識點。
單一職責原則的核心思想是讓每個類專注於一個明確的職責,以提高程式碼的可維護性和可讀性。適用於類、介面、方法中。
單一職責原則的難點在於如何將類的職責劃分得清晰明瞭,如何識別和消除不必要的職責......。在實際開發中,我們很容易將不同的責任歸類在一起,或者過度拆分。
是否需要拆分職責,參考思路:當變化發生,隻影響其中一個職責,那就需要拆分。如果變化都影響到這兩個職責,那就不需要拆分。
合理拆分職責的前提:設計者需要對業務足夠了解、同時具備較強的分析設計能力及相關實踐經驗,這個部分在 Mike 的架構專題中有詳解。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70024924/viewspace-2991288/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 單一職責原則
- 設計原則之【單一職責原則】
- 單一職責原則筆記筆記
- 單一職責原則詳解
- 編碼最佳實踐——單一職責原則
- 設計模式六大原則(一)----單一職責原則設計模式
- 被誤解的單一職責原則 - Joe
- 程式碼質量-開閉原則
- [譯] 更可靠的 React 元件:單一職責原則React元件
- 單一職責原則在 iOS 中的應用iOS
- 面象物件設計6大原則之一:單一職責原則物件
- 設計模式的七大原則(1) --單一職責原則設計模式
- 嘻哈說:設計模式之單一職責原則設計模式
- 單一職責原則:軟體世界中最重要的規則 - DZone
- 《JavaScript設計模式與開發實踐》原則篇(1)—— 單一職責原則JavaScript設計模式
- 將單一職責原則應用於前端FE/BFF分層架構 - Expedia前端架構
- Laravel深入學習8 – 單一責任原則Laravel
- 保持類的單一職責
- 設計模式 - 單一職責設計模式
- 如何提升 Web 應用的程式碼質量Web
- 利用SonarCloud和Azure DevOps提升程式碼質量Clouddev
- 清潔程式碼:職責 — Janos Pasztor
- 《程式碼整潔之道》精華速覽,助你提升程式碼質量
- 如何更好的做單元測試並用它來提升程式碼質量(下)
- 前端程式碼質量管理(一)前端
- .NET Core TDD 前傳: 編寫易於測試的程式碼 -- 單一職責
- 領域知識與SOLID單一責任原則的解釋Solid
- 掌握這些程式碼安全檢視方法,提升你的程式碼質量
- 程式碼重構之道:消滅冗長的if語句,提升程式碼質量
- 重構 - 保持函式的單一職責函式
- 網站最佳化崗位職責描述,明確職責,提升工作效率!網站
- 一起玩轉微服務(7)——單一職責微服務
- 如何利用大模型提升前端研發效率和程式碼質量大模型前端
- 前端質量提升利器-馬可程式碼覆蓋率平臺前端
- 對待資料質量的28個原則
- 質量管理三不原則的基本做法
- S.O.I.L.D 之單一職責
- 程式設計師必看:如何充分利用程式碼審查提升你的程式碼質量?程式設計師