Factory Method 工廠方法是一種創建型設計模式:Superclass 先粗略定義 Object 的創建方法,但允許 Subclass 詳細定義 Object 的創建方法。
舉例來說,運輸總公司(Superclass)持有一張廣義運輸工具的設計圖(Interface),總公司只宣告要生產廣義的運輸工具(Product),這些運輸工具會在南北之間來回送貨(運作邏輯),但沒寫要生產貨車還是船,然後根據設計圖,陸路運輸公司(Subclass)製造貨車(Product),海路運輸公司(Subclass)製造船(Product)。同時陸路運輸公司、海路運輸公司都直接利用設計圖裡面寫好的送貨方法。
比較正式地說,Superclass 透過 Interface 定義某類 Object 粗略的創建方法,並且定義這類 Object 共同的運作邏輯,然後再讓 Subclass 詳細重寫該類 Object 的創建方法。而這些透過 Factory Method 產生的 Object 稱為 Product。
讓陸路運輸公司獨立生產貨車,設計貨車的送貨方法;而海路運輸公司獨立生產船,設計船的送貨方法呢?
陸路運輸公司、海路運輸公司都自己寫了一份送貨方法,不只多餘,每次要改什麼還要改兩次。如果之後要加入飛機空運,送貨方法再寫一次,崩潰。
運輸總公司一起生產貨車、船,設計一套送貨邏輯給船跟貨車一起用呢?
送貨邏輯裡面就會夾雜很多 if/else:看到貨車就跑陸路,看到船就走海路。之後又要加入飛機空運,再度崩潰。
除了以上好處,Factory Method 同時也符合計算機科學中的兩個設計原則,首先是單一功能原則:創建 product 的程式碼都在同一個地方 (factory_method),而使其更容易維護;第二則是開閉原則:因為送貨方法和 product 類型無關,所以就算加入新的 product 類型也無需更改送貨方法。
而壞處呢,一大堆 subclasses 會讓程式碼變的更複雜,但無論使用 Factory Method 與否,一大堆subclasses/classes 在這種情境中難以避免的。
from abc import ABC
class Logistics(ABC):
# 初始化透過factory method創建product
def __init__(self):
self.product = self.factory_method()
# 抽象的product創建方法
def factory_method(self):
pass
# 卡車和船共通的送貨邏輯
def run_delivery(self):
print("Running some complex operations")
self.product.deliver()
# 陸路運輸公司
class RoadLogistics(Logistics):
# 重寫工廠方法
def factory_method(self):
return Truck()
# 海路運輸公司
class SeaLogistics(Logistics):
# 重寫工廠方法
def factory_method(self):
return Ship()
# 廣義的運輸工具
class Transport(ABC):
# 會運輸
def deliver(self):
pass
# 貨車
class Truck(Transport):
# 會走陸路運輸
def deliver(self):
print("truck delivering stuff")
# 船
class Ship(Transport):
# 會走海路運輸
def deliver(self):
print("ship delivering stuff")
if __name__ == "__main__":
# 假設陸路運輸公司那邊要製造貨車來送貨
logistics = RoadLogistics()
logistics.run_delivery()
在一般專案初期,我們可以先使用較簡單的 Factory Method 來創建 Object,之後如果想要更靈活地創建 Object,我們也可以改用較複雜的 Abstract Factory,Prototype,或是 Builder 等創建型設計模式。
等一下,Abstract Factory、Prototype、Builder又是什麼東西?
想了解更多,就請持續關注我們接下來的文章吧!
作者:Allen