1. 什么是構建模式
構建模式(Builder Pattern)是一種創建型設計模式,它允許使用多個簡單的對象一步步構建一個復雜的對象。構建模式通過將構建過程與表示分離,使得同樣的構建過程可以創建不同的表示。換句話說,構建模式提供了一種靈活的方式來創建復雜對象,避免了構造函數參數過多的問題。
- 工廠模式通過一個工廠類來創建對象,適合于創建多個相似對象,隱藏了對象創建的具體實現。
- 構建模式通過構建者和指揮者的組合,逐步構建一個復雜對象,適合于需要多個步驟和多個部分的組合。
- 組合模式則允許將對象組合成樹形結構,適合于處理部分和整體的層次關系。
1.1 工廠模式與構建模式的對比
在工廠模式中,我們將創建一個簡單的汽車工廠來生成汽車對象。
class Car:def __init__(self, make, model):self.make = makeself.model = modeldef __str__(self):return f"{self.make} {self.model}"class CarFactory:@staticmethoddef create_car(make, model):return Car(make, model)# 客戶端代碼
if __name__ == "__main__":car1 = CarFactory.create_car("Toyota", "Camry")car2 = CarFactory.create_car("Honda", "Accord")print(car1) # 輸出: Toyota Camryprint(car2) # 輸出: Honda Accord
在構建模式中,我們將使用構建者模式逐步構建一個復雜的汽車對象。
# 產品類
class Car:def __init__(self):self.make = Noneself.model = Noneself.year = Noneself.color = Nonedef __str__(self):return f"{self.year} {self.color} {self.make} {self.model}"# 構建者接口
class CarBuilder:def set_make(self, make):passdef set_model(self, model):passdef set_year(self, year):passdef set_color(self, color):passdef build(self):pass# 具體構建者
class ConcreteCarBuilder(CarBuilder):def __init__(self):self.car = Car()def set_make(self, make):self.car.make = makedef set_model(self, model):self.car.model = modeldef set_year(self, year):self.car.year = yeardef set_color(self, color):self.car.color = colordef build(self):return self.car# 指揮者
class Director:def __init__(self, builder):self.builder = builderdef construct_car(self, make, model, year, color):self.builder.set_make(make)self.builder.set_model(model)self.builder.set_year(year)self.builder.set_color(color)return self.builder.build()# 客戶端代碼
if __name__ == "__main__":builder = ConcreteCarBuilder()director = Director(builder)# 構建一輛車car = director.construct_car("Toyota", "Camry", 2022, "Blue")print(car) # 輸出: 2022 Blue Toyota Camry
1.2 組合模式與構建模式的對比
在組合模式中,我們將創建一個文件系統的結構,允許文件和文件夾以樹形結構組合。
class Component:def operation(self):passclass File(Component):def __init__(self, name):self.name = namedef operation(self):return f"File: {self.name}"class Folder(Component):def __init__(self, name):self.name = nameself.children = []def add(self, component):self.children.append(component)def remove(self, component):self.children.remove(component)def operation(self):results = [f"Folder: {self.name}"]for child in self.children:results.append(child.operation())return "\n".join(results)# 客戶端代碼
if __name__ == "__main__":file1 = File("file1.txt")file2 = File("file2.txt")folder1 = Folder("Folder 1")folder1.add(file1)folder1.add(file2)print(folder1.operation())
在構建模式中,我們將使用構建者模式逐步構建一個復雜的文件對象。
class File:def __init__(self, name):self.name = namedef __str__(self):return f"File: {self.name}"class Folder:def __init__(self, name):self.name = nameself.children = []def add(self, component):self.children.append(component)def remove(self, component):self.children.remove(component)def __str__(self):results = [f"Folder: {self.name}"]for child in self.children:results.append(str(child))return "\n".join(results)class FileBuilder:def __init__(self):self.folder = Nonedef create_folder(self, name):self.folder = Folder(name)def add_file(self, file_name):if self.folder:self.folder.add(File(file_name))def build(self):return self.folder# 客戶端代碼
if __name__ == "__main__":builder = FileBuilder()builder.create_folder("Folder 1")builder.add_file("file1.txt")builder.add_file("file2.txt")folder = builder.build()print(folder) # 輸出: Folder: Folder 1\nFile: file1.txt\nFile: file2.txt
2. 構建模式的結構
構建模式通常包含以下幾個角色:
- 產品(Product):表示被構建的復雜對象。
- 構建者(Builder):定義了創建產品的抽象接口,包含構建產品的各個部分的方法。
- 具體構建者(ConcreteBuilder):實現了構建者接口,負責構建產品的具體部分。
- 指揮者(Director):負責管理構建過程,使用構建者來構建產品。
# 產品類
class Car:def __init__(self):self.make = Noneself.model = Noneself.year = Noneself.color = Nonedef __str__(self):return f"{self.year} {self.color} {self.make} {self.model}"# 構建者接口
class CarBuilder:def set_make(self, make):passdef set_model(self, model):passdef set_year(self, year):passdef set_color(self, color):passdef build(self):pass# 具體構建者
class ConcreteCarBuilder(CarBuilder):def __init__(self):self.car = Car()def set_make(self, make):self.car.make = makedef set_model(self, model):self.car.model = modeldef set_year(self, year):self.car.year = yeardef set_color(self, color):self.car.color = colordef build(self):return self.car# 指揮者
class Director:def __init__(self, builder):self.builder = builderdef construct_car(self, make, model, year, color):self.builder.set_make(make)self.builder.set_model(model)self.builder.set_year(year)self.builder.set_color(color)return self.builder.build()# 客戶端代碼
if __name__ == "__main__":builder = ConcreteCarBuilder()director = Director(builder)# 構建一輛車car = director.construct_car("Toyota", "Camry", 2022, "Blue")print(car) # 輸出: 2022 Blue Toyota Camry
-
產品類(Car):表示被構建的復雜對象,包含多個屬性(如品牌、型號、年份和顏色),并實現了一個
__str__
方法用于輸出對象的字符串表示。 -
構建者接口(CarBuilder):定義了創建產品的抽象接口,包含設置汽車各個屬性的方法。
-
具體構建者(ConcreteCarBuilder):實現了構建者接口,負責實現構建汽車的具體部分。它創建一個
Car
對象并逐步設置其屬性,最后返回構建好的Car
對象。 -
指揮者(Director):負責管理構建過程,使用構建者來構建產品。它接受一個構建者對象,并通過調用構建者的方法來構建一個完整的
Car
對象。 -
客戶端代碼:創建了一個
ConcreteCarBuilder
實例和一個Director
實例。通過指揮者的construct_car
方法,逐步構建了一輛汽車,并最終輸出了構建好的汽車對象。
3. 示例 1:構建復雜的餐廳訂單系統
在日常開發中,構建模式常用于構建復雜對象的場景。一個典型的例子是餐廳訂單系統。在這個系統中,顧客可以選擇不同的菜品、飲料和配餐,最終生成一個完整的訂單。使用構建模式可以有效地管理這個復雜的構建過程。
在這個示例中,我們將創建一個訂單對象,顧客可以通過不同的步驟來構建這個訂單。我們將定義以下角色:
- 產品(Order):表示顧客的訂單,包含多個菜品和飲料。
- 構建者(OrderBuilder):定義了創建訂單的抽象接口,包含添加菜品和飲料的方法。
- 具體構建者(ConcreteOrderBuilder):實現了構建者接口,負責構建訂單的具體部分。
- 指揮者(Director):負責管理構建過程,使用構建者來構建訂單。
# 產品類
class Order:def __init__(self):self.dishes = []self.drinks = []def add_dish(self, dish):self.dishes.append(dish)def add_drink(self, drink):self.drinks.append(drink)def __str__(self):order_details = "Order Details:\n"order_details += "Dishes:\n" + "\n".join(self.dishes) + "\n"order_details += "Drinks:\n" + "\n".join(self.drinks)return order_details# 構建者接口
class OrderBuilder:def add_dish(self, dish):passdef add_drink(self, drink):passdef build(self):pass# 具體構建者
class ConcreteOrderBuilder(OrderBuilder):def __init__(self):self.order = Order()def add_dish(self, dish):self.order.add_dish(dish)def add_drink(self, drink):self.order.add_drink(drink)def build(self):return self.order# 指揮者
class Director:def __init__(self, builder):self.builder = builderdef construct_order(self, dishes, drinks):for dish in dishes:self.builder.add_dish(dish)for drink in drinks:self.builder.add_drink(drink)return self.builder.build()# 客戶端代碼
if __name__ == "__main__":builder = ConcreteOrderBuilder()director = Director(builder)# 構建一個訂單dishes = ["Spaghetti", "Caesar Salad", "Grilled Chicken"]drinks = ["Coke", "Water"]order = director.construct_order(dishes, drinks)print(order) # 輸出訂單詳情
Order Details:
Dishes:
Spaghetti
Caesar Salad
Grilled Chicken
Drinks:
Coke
Water
-
產品類(Order):表示顧客的訂單,包含多個菜品和飲料。它提供了添加菜品和飲料的方法,并實現了一個
__str__
方法用于輸出訂單的詳細信息。 -
構建者接口(OrderBuilder):定義了創建訂單的抽象接口,包含添加菜品和飲料的方法。
-
具體構建者(ConcreteOrderBuilder):實現了構建者接口,負責構建訂單的具體部分。它創建一個
Order
對象并逐步添加菜品和飲料,最后返回構建好的訂單對象。 -
指揮者(Director):負責管理構建過程,使用構建者來構建訂單。它接受一個構建者對象,并通過調用構建者的方法來構建一個完整的訂單對象。
-
客戶端代碼:創建了一個
ConcreteOrderBuilder
實例和一個Director
實例。通過指揮者的construct_order
方法,逐步構建了一個訂單,并最終輸出了訂單的詳細信息。