模式為反覆出現的設計取捨命名。Java 語言功能可以實作模式,但 lambda 或相依性注入容器本身都不能取代設計決策。
建立型模式 #
當呼叫端不應依賴具體型別,或建構過程會選取實作時,**Factory(工廠)**會集中處理建構。工廠隱藏有用的細節,但為每個產品提供一個方法的工廠可能會變成不必要的間接層。
interface Parser { Document parse(String text); }
final class Parsers {
static Parser forFormat(Format format) { return format::parse; }
}**Builder(建造者)**會收集選用引數,並在產生不可變值之前驗證跨欄位不變量。必要欄位很少時,使用建構函式或靜態工廠;只反映 setter 的 builder 會掩蓋必要狀態。對 Java 而言,**Prototype(原型)**通常使用明確的複製建構函式或 copyOf 工廠,比 Cloneable 更清楚,因為 Cloneable 的淺層複製與繼承語意難以安全擴充。
結構型模式 #
**Adapter(轉接器)**會將外部介面轉換成應用程式擁有的契約。它能避免廠商型別散布到領域層,但代價是必須維護轉換。**Decorator(裝飾器)**會在相同介面周圍加入行為:
final class MeteredStore implements Store {
private final Store delegate;
public Value get(Key key) {
metrics.recordAttempt();
return delegate.get(key);
}
}當快取、授權與指標等關注事項彼此獨立變化時,裝飾器組合優於子類別組合。Java I/O 串流就是經典範例。當 Facade(外觀)與 Composite(組合)能簡化刻意設計的複雜子系統,或表達整體—部分樹狀結構時,它們同樣有用。
行為型模式 #
**Strategy(策略)**會在穩定介面後方選取演算法。Java 可以使用介面實作、函數式介面的 lambda,或封閉策略集合的列舉常數來表達策略:
enum Rounding {
DOWN { BigDecimal apply(BigDecimal n) { return n.setScale(0, RoundingMode.DOWN); } },
UP { BigDecimal apply(BigDecimal n) { return n.setScale(0, RoundingMode.UP); } };
abstract BigDecimal apply(BigDecimal n);
}**Observer(觀察者)**會將事件發布給監聽器。應指定同步或非同步傳遞、順序、失敗隔離、反壓與監聽器擁有權;否則觀察者清單會變成隱藏的控制流程。當 Command(命令)、Template Method(樣板方法)、Iterator(迭代器)與 State(狀態)模式能在不使用大型條件式的情況下明確表達變化時,它們仍然有用。
相依性注入會從物件外部提供協作者。它可以連接工廠、策略、裝飾器與觀察者,但不會決定它們的界線。同樣地,record、sealed type、switch 與 lambda 能減少樣板程式碼;它們不會決定領域應由開放式多型或封閉集合建模。
評論
在 GitHub 上閱讀或評論(發表評論需要登入)