沒錯!您的直覺非常準確,這正是整個創建型模式(Creational Patterns)核心要解決的根本問題。
在軟體開發中,直接使用
new 關鍵字來建立物件(例如 MyClass obj = new MyClass();)雖然直覺又方便,但在中大型系統或需要高度擴充性的架構中,直接使用 new 會帶來幾個致命的痛點。創建型模式的存在,就是為了將「物件的建立邏輯」與「物件的使用方式」徹底解耦。直接使用
new 會遇到以下幾種不適合的狀況:1. 緊密耦合(Tight Coupling)與無法抽換實作
當你在程式碼各處直接
new SpecificClass() 時,你的程式碼就和這個具體類別(Concrete Class)綁死了。- 問題: 如果有一天業務需求改變,需要將
MySQLDatabase改成PostgreSQLDatabase,或者需要換成用於單元測試的MockDatabase,你就必須去修改所有出現new MySQLDatabase()的地方。 - 解法: 透過 Factory 或是依賴注入(Dependency Injection),讓程式碼只依賴介面(Interface),由工廠在背後決定要
new哪個具體物件。
2. 物件建立過程極為繁複(Complex Initialization)
有些物件的誕生不是單純呼叫無參數建構子就能搞定的,它可能需要:
- 依序讀取設定檔、連線資料庫、初始化緩衝區。
- 傳入一長串複雜的參數(Constructor Pollution,例如
new User("John", 30, "Taiwan", null, true, ...))。 - 步驟必須按照特定順序執行。
- 問題: 如果將這些複雜的初始化邏輯全部寫在商業邏輯程式碼中,會導致程式碼極度臃腫且難以維護。
- 解法: 像是 Builder(建造者模式) 或 Abstract Factory(抽象工廠) 就是專門用來把這些繁複的建造細節封裝起來,讓呼叫端只要簡單呼叫「請給我一個物件」即可。
3. 無法控制實例數量與資源開銷(Lifecycle & Resource Control)
直接用
new 的另一個問題是:呼叫端無法限制總共被建立了幾個物件。- 問題: 有些物件(如資料庫連線池、執行緒池、全域設定管理器)如果在系統中被
new出好幾個實例,會導致記憶體暴增、資源衝突或資料不同步。 - 解法: Singleton(單例模式) 就是為了防止外部隨意
new,強制控制整個生命週期中只能有一個實例。
4. 需要在執行時期(Runtime)才決定要建立哪種物件
有時候,要在寫程式(Compile time)的當下,根本不知道該建立哪一個類別的物件,必須根據使用者的輸入、檔案格式或環境變數來決定。
- 問題: 如果用傳統的
new,會被迫寫出龐大且充滿擴充危機的if-else或switch-case判斷式。 - 解法: Factory Method(工廠方法) 或 Prototype(原型模式) 允許系統在執行時期動態決定該實例化哪一個類別,甚至直接透過複製現有物件來衍生新物件。
💡 總結
直接用
new 就像是「自己動手做每一個零件」;而使用創建型模式,就像是「委託專門的工廠或師傅來幫你生產」。- 直接
new:適合簡單、小型、短期、不需要太高擴充性的腳本或小程式。 - 創建型模式:適合需要易於維護、易於寫單元測試、架構需長期演進的中大型系統。
沒有留言:
張貼留言