C# 介面提供鬆耦合—經由 Tim Corey 的第 16 課解釋
在"C#應用程式從頭到尾"課程的第16課中,Tim Corey繼續建立創建比賽表單,但是實際的學習目標遠遠超過連接按鈕和列表框。 當Tim完成表單之間的連接時,他介紹了一個C#中的核心軟體設計概念:用於鬆散耦合的介面。 這節課展示了介面不僅僅是一個抽象的學術概念,而是一個解決WinForms應用程式中真實問題的實用工具。
在這篇文章中,我們深入探討Tim Corey如何解釋介面,為什麼他要使用它們,以及它們如何幫助避免緊耦合。 所有的解釋、推理和結論都直接來自Tim的講解,使用了他的流程、術語和示例自轉錄本中。
連接表單很容易——正確連接它們則不然
在1:18,Tim開始連接創建獎品和創建團隊的介面元素。 他立即指出,這一步可能讓人感到害怕,不是因為呼叫另一個表單很難,而是因為正確返回資料是人們通常出錯的地方。
Tim解釋說,挑戰不是打開另一個表單——這部分很容易。 挑戰在於一個表單如何與另一個表單通信而不產生長期的設計問題。 這就是確定契約而非依賴的想法開始變得重要的地方。
緊耦合的誘惑
在1:34左右,Tim明確指明了一個常見的錯誤:直接將創建比賽表單與創建獎品表單聯繫起來。 在這種方法中,一個類確切知道它正在與哪一個其它類進行對話。
Tim解釋說,這會導致緊耦合,意味著這些表單彼此直接相互依賴。 如果一個表單發生變更,另一個表單會受到影響。 如果程式的其他部分以後想要相同的功能,則不能重用它。
他強調,雖然這可能會編譯和工作,但對於大型系統或專業環境來說,這不是一個好的長期設計選擇。
在寫代碼之前思考步驟
在2:02,Tim暫停一下,列出步驟而不是直接進入代碼。 他列出了:
-
呼叫創建獎品表單
-
獲得一個PrizeModel返回
- 將其添加到所選獎品清單中
Tim解釋說,首先寫下步驟有助於避免邏輯錯誤,並使代碼的意圖清晰。 這種結構化思考變得尤為重要,因為介面被引入,因為介面定義了必須發生的事情,而不是如何發生。
引用類型和為什麼不總是需要返回值
在4:56左右,Tim解釋了一個關於傳遞模型的重要細節。 他提醒觀眾,他們在傳遞地址,而不是對象的副本。
當通過數據連結器保存獎品時,模型已經填充了其ID。 Tim指出,因為實例已經被修改,所以再次返回模型通常是沒必要的。
這強調了介面並非為了盲目地移動數據而存在——它們存在於信號完成和責任,而不是重複。
為什麼首先傳遞模型是一個壞主意
在6:42,Tim討論了將PrizeModel傳入表單構造函數的想法,這樣兩個表單可以共享同一實例。
他解釋了為什麼這在一個實際用例中失敗:如果用戶取消表單,則您的清單中可能有一個空的或無效的獎品。Tim顯示,僅僅因為兩個類可以共享實例數據不意味著它們應該這樣做。
這一刻強調了介面定義行為,而不是數據存儲。
直接傳遞呼叫表單更糟
在7:46左右,Tim提出了另一個常見的方法:將整個創建比賽表單傳入創建獎品表單中並調用一個公共方法,如SavePrize。
Tim解釋為什麼這更糟:
-
獎品表單現在確切知道是哪一個類在呼叫它
-
沒有其他不相關的類可以重用獎品表單
- 類被鎖定在一個單一的用例中
他明確將其命名為緊耦合,這是我們要避免的。
引入介面作為契約
在9:01,Tim引入了解決方案:一個介面。
他使用介面關鍵字創建了一個新的介面,並命名為IPrizeRequester。 Tim提醒觀眾,介面:
-
不是一個類
-
不包含具體的方法
- 存在於定義一份契約
這個介面包含一個方法:
- PrizeComplete(PrizeModel model)
Tim解釋說,這個方法定義了必須發生的事情,而不是如何發生。
介面成員和責任
在9:40,Tim解釋誰實施這個介面,誰就同意支持該方法。 介面默認具有公共成員,且不聲明實例數據。
這是Tim說明介面定義能力,而不是存儲的地方。 實施類決定在該方法被調用時做什麼。
傳遞介面類型而不是類
在10:19,Tim修改了創建獎品表單構造函數,以接受某個IPrizeRequester而不是具體的表單。
他解釋說,這意味著:
-
有人將會呼叫該表單
-
該表單不知道那是誰
- 唯一的要求是呼叫者實施了該介面
這是鬆散耦合的實踐。獎品表單依賴於介面類型,而不是特定的類。
儲存介面實例以便將來使用
在11:06,Tim在類級別儲存了介面實例。 他解釋說,構造函數參數只在構造函數內存在,除非它們被儲存。
這允許獎品表單稍後從按鈕點擊事件內部呼叫PrizeComplete。
回調實施類
在11:49,Tim顯示了關鍵時刻:
callingForm.PrizeComplete(model);
他解釋說,獎品表單現在回調到誰實施了該介面並說:
"我完成了,這是完整的模型。"
只有在此呼叫之後,表單才會關閉。 這保證獎品僅在創建成功時被添加。
在比賽表單中實施介面
在13:29,Tim轉到創建比賽表單並實施了介面。
他在13:58解釋了this關鍵字,描述為當前實例——記憶體中的實際對象。 通過傳遞this,表單是在交出自己的地址,但僅通過介面契約。
多個介面,一個類
在18:41,Tim引入了第二個介面:ITeamRequester。
他解釋說,儘管一個類只能從一個基類繼承(如Form),但它可以實施多個介面。 這允許一個類支持多個不相關的行為,而不需要使用多重繼承。
Tim強調,介面不會引入代碼——它們只定義所需的方法。
模式、一致性和錯誤檢測
在42:08左右,Tim反思為什麼使用模式很重要。 重複相同的基於介面的結構使得錯失步驟顯而易見,並且調試更容易。
Tim鼓勵將事情寫下來,使用一致的模式,並且不要試圖將所有事情都放在你的腦子裡。 據他說,好的設計不在於完美——而在於清晰、結構化,並使將來的變更更容易。
結論
在第16課中,Tim Corey使用了一個真實的WinForms使用案例來演示介面如何實現鬆散耦合。 而不是依賴於抽象的例子,他顯示了介面如何:
-
定義契約
-
解耦類
-
在單個類中支持多個介面
-
防止緊耦合
- 改善長期靈活性
在課程結束時,應用程式不僅僅能運作——它結構支持增長、重用和清晰性。 Tim的方法使得介面在真實世界的C#開發中感覺實際、有目的且必不可少。
要完整地查看這些介面和鬆散耦合概念的端到端應用,請觀看完整的第16課影片,每一步都在工作的C#應用程式中實施、測試和完善。
