概述#

Creational pattern 抽象化了物件的實例化過程(instantiation process),使系統不依賴於物件如何被建立、組合和表示。其中:

  • Class creational pattern 使用繼承來改變被實例化的 class
  • Object creational pattern 將實例化委託給另一個物件

隨著系統演進,越來越依賴**物件組合(object composition)**而非 class 繼承,creational pattern 的重要性也隨之增加——建立具有特定行為的物件不再只是簡單地實例化一個 class。

兩個核心主題#

所有 creational pattern 都圍繞著兩個反覆出現的主題:

  1. 封裝具體 class 的知識:系統只透過 abstract class 定義的介面認識物件
  2. 隱藏實例的建立與組裝方式:提供極大的彈性來決定 what(建立什麼)、who(誰來建立)、how(如何建立)、when(何時建立)

Creational pattern 之間有時是競爭者(例如 Prototype 和 Abstract Factory 可互相替代),有時是互補的(例如 Builder 可以使用其他 pattern 來決定建造哪些元件,Prototype 可以在實作中使用 Singleton)。

Maze 範例#

本書使用一個共通範例——電腦遊戲中的迷宮(maze)——來展示各個 creational pattern 的實作差異。

迷宮由以下元件組成:

  • MapSite:所有迷宮元件的共同抽象 class,定義 Enter 操作
  • RoomMapSite 的具體子類別,維護四面的鄰居參照與房間編號
  • WallDoor:出現在房間各面的牆壁或門
  • Maze:房間的集合,可透過 RoomNo 找到特定房間
  • MazeGame:建立迷宮的 class

直接在 CreateMaze 中硬編碼建立流程的問題是缺乏彈性——想要改變迷宮元件(例如 EnchantedRoomDoorNeedingSpell)就必須修改整個函式。

五種 Creational Pattern 的解法#

各 pattern 以不同方式移除對具體 class 的顯式參照:

Pattern解法
Factory MethodCreateMaze 呼叫 virtual function 而非 constructor,透過子類別化 MazeGame 來改變實例化的 class
Abstract Factory將建立物件的工廠作為參數傳入 CreateMaze,替換不同的工廠就能改變元件類型
Builder傳入一個能用操作逐步建造迷宮的物件,可透過繼承改變建造方式或元件
Prototype以各種原型物件(prototypical room、door、wall)參數化 CreateMaze,透過複製原型來建立新元件
Singleton確保每個遊戲只有一個 maze 實例,所有遊戲物件都能存取它,且不需依賴全域變數