Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

設計模式指南 - Python 範例

一、創建型模式 (Creational Patterns)

1. 單例模式 (Singleton Pattern)

精神:確保一個類別只有一個實例,並提供全域訪問點。

白話解釋:就像一個國家只有一個總統,整個系統只需要一個物件實例。

常見用法:資料庫連線、設定檔管理、日誌記錄器

class DatabaseConnection:
    _instance = None
    
    def __new__(cls):
        if cls._instance is None:
            cls._instance = super().__new__(cls)
            cls._instance.connection = "資料庫連線建立"
        return cls._instance
    
# 使用範例
db1 = DatabaseConnection()
db2 = DatabaseConnection()
print(db1 is db2)  # True,兩個變數指向同一個實例

2. 工廠模式 (Factory Pattern)

精神:定義一個創建物件的介面,讓子類別決定實例化哪個類別。

白話解釋:像是餐廳點餐,你說要什麼,廚房就做什麼給你,你不需要知道怎麼做。

常見用法:根據條件創建不同類型的物件

class Animal:
    def speak(self):
        pass

class Dog(Animal):
    def speak(self):
        return "汪汪!"

class Cat(Animal):
    def speak(self):
        return "喵喵!"

class AnimalFactory:
    @staticmethod
    def create_animal(animal_type):
        if animal_type == "dog":
            return Dog()
        elif animal_type == "cat":
            return Cat()
        else:
            return None

# 使用範例
factory = AnimalFactory()
dog = factory.create_animal("dog")
print(dog.speak())  # 汪汪!

3. 建造者模式 (Builder Pattern)

精神:將複雜物件的建構過程分離,使同樣的建構過程可以創建不同的表示。

白話解釋:像組裝電腦,可以選擇不同的 CPU、記憶體、硬碟,最後組成一臺完整的電腦。

常見用法:創建有許多選項的複雜物件

class Computer:
    def __init__(self):
        self.cpu = None
        self.ram = None
        self.storage = None
    
    def __str__(self):
        return f"電腦配置:CPU={self.cpu}, RAM={self.ram}, Storage={self.storage}"

class ComputerBuilder:
    def __init__(self):
        self.computer = Computer()
    
    def set_cpu(self, cpu):
        self.computer.cpu = cpu
        return self
    
    def set_ram(self, ram):
        self.computer.ram = ram
        return self
    
    def set_storage(self, storage):
        self.computer.storage = storage
        return self
    
    def build(self):
        return self.computer

# 使用範例
gaming_pc = ComputerBuilder()\
    .set_cpu("Intel i9")\
    .set_ram("32GB")\
    .set_storage("2TB SSD")\
    .build()
print(gaming_pc)

二、結構型模式 (Structural Patterns)

4. 轉接器模式 (Adapter Pattern)

精神:將一個類別的介面轉換成客戶希望的另一個介面。

白話解釋:像是電源轉接頭,讓不同規格的插頭可以連接使用。

常見用法:整合第三方程式庫、舊系統相容

# 舊的支付系統
class OldPaymentSystem:
    def make_payment(self, amount):
        return f"舊系統:支付 ${amount}"

# 新的支付介面
class NewPaymentInterface:
    def pay(self, amount):
        pass

# 轉接器
class PaymentAdapter(NewPaymentInterface):
    def __init__(self, old_system):
        self.old_system = old_system
    
    def pay(self, amount):
        return self.old_system.make_payment(amount)

# 使用範例
old_system = OldPaymentSystem()
adapter = PaymentAdapter(old_system)
print(adapter.pay(100))  # 舊系統:支付 $100

5. 裝飾者模式 (Decorator Pattern)

精神:動態地給物件添加新功能,不改變其結構。

白話解釋:像是咖啡加料,基本咖啡可以加牛奶、加糖、加奶泡,每加一樣就多一個功能。

常見用法:動態添加功能、權限驗證、日誌記錄

class Coffee:
    def cost(self):
        return 30
    
    def description(self):
        return "基本咖啡"

class MilkDecorator:
    def __init__(self, coffee):
        self.coffee = coffee
    
    def cost(self):
        return self.coffee.cost() + 10
    
    def description(self):
        return self.coffee.description() + " + 牛奶"

class SugarDecorator:
    def __init__(self, coffee):
        self.coffee = coffee
    
    def cost(self):
        return self.coffee.cost() + 5
    
    def description(self):
        return self.coffee.description() + " + 糖"

# 使用範例
coffee = Coffee()
coffee_with_milk = MilkDecorator(coffee)
coffee_with_milk_sugar = SugarDecorator(coffee_with_milk)

print(coffee_with_milk_sugar.description())  # 基本咖啡 + 牛奶 + 糖
print(f"價格:${coffee_with_milk_sugar.cost()}")  # 價格:$45

6. 外觀模式 (Facade Pattern)

精神:為子系統中的一組介面提供一個統一的高層介面。

白話解釋:像是家庭劇院的遙控器,一個按鈕就能開啟電視、音響、調光等多個設備。

常見用法:簡化複雜系統的操作介面

class TV:
    def turn_on(self):
        return "電視開啟"
    
class SoundSystem:
    def turn_on(self):
        return "音響開啟"
    
class Lights:
    def dim(self):
        return "燈光調暗"

class HomeTheaterFacade:
    def __init__(self):
        self.tv = TV()
        self.sound = SoundSystem()
        self.lights = Lights()
    
    def watch_movie(self):
        results = []
        results.append(self.tv.turn_on())
        results.append(self.sound.turn_on())
        results.append(self.lights.dim())
        return " -> ".join(results)

# 使用範例
theater = HomeTheaterFacade()
print(theater.watch_movie())  # 電視開啟 -> 音響開啟 -> 燈光調暗

三、行為型模式 (Behavioral Patterns)

7. 觀察者模式 (Observer Pattern)

精神:定義物件間一對多的依賴關係,當一個物件狀態改變時,所有依賴者都會收到通知。

白話解釋:像是訂閱 YouTube 頻道,頻道更新影片時,所有訂閱者都會收到通知。

常見用法:事件處理、模型-視圖架構、訊息推播

class YouTubeChannel:
    def __init__(self, name):
        self.name = name
        self.subscribers = []
    
    def subscribe(self, subscriber):
        self.subscribers.append(subscriber)
    
    def notify(self, video):
        for subscriber in self.subscribers:
            subscriber.update(self.name, video)
    
    def upload_video(self, video):
        print(f"{self.name} 上傳了:{video}")
        self.notify(video)

class Subscriber:
    def __init__(self, name):
        self.name = name
    
    def update(self, channel, video):
        print(f"{self.name} 收到通知:{channel} 上傳了 {video}")

# 使用範例
channel = YouTubeChannel("科技頻道")
subscriber1 = Subscriber("小明")
subscriber2 = Subscriber("小華")

channel.subscribe(subscriber1)
channel.subscribe(subscriber2)
channel.upload_video("Python 教學")

8. 策略模式 (Strategy Pattern)

精神:定義一系列演算法,把它們封裝起來,並且使它們可以互相替換。

白話解釋:像是出門選擇交通工具,可以開車、騎車或搭捷運,根據情況選擇不同策略。

常見用法:支付方式選擇、排序演算法選擇、資料驗證

class PaymentStrategy:
    def pay(self, amount):
        pass

class CreditCardPayment(PaymentStrategy):
    def pay(self, amount):
        return f"使用信用卡支付 ${amount}"

class CashPayment(PaymentStrategy):
    def pay(self, amount):
        return f"使用現金支付 ${amount}"

class MobilePayment(PaymentStrategy):
    def pay(self, amount):
        return f"使用行動支付 ${amount}"

class ShoppingCart:
    def __init__(self, payment_strategy):
        self.payment_strategy = payment_strategy
    
    def checkout(self, amount):
        return self.payment_strategy.pay(amount)

# 使用範例
cart = ShoppingCart(CreditCardPayment())
print(cart.checkout(1000))  # 使用信用卡支付 $1000

cart.payment_strategy = MobilePayment()
print(cart.checkout(500))   # 使用行動支付 $500

9. 模板方法模式 (Template Method Pattern)

精神:定義演算法的骨架,將一些步驟延遲到子類別中實現。

白話解釋:像是泡茶和泡咖啡,步驟類似(煮水、沖泡、倒入杯子、加調料),但細節不同。

常見用法:資料處理流程、遊戲回合制流程

from abc import ABC, abstractmethod

class DataProcessor(ABC):
    def process(self):
        self.read_data()
        self.process_data()
        self.save_data()
    
    @abstractmethod
    def read_data(self):
        pass
    
    @abstractmethod
    def process_data(self):
        pass
    
    def save_data(self):
        print("儲存處理後的資料")

class CSVProcessor(DataProcessor):
    def read_data(self):
        print("讀取 CSV 檔案")
    
    def process_data(self):
        print("處理 CSV 資料")

class JSONProcessor(DataProcessor):
    def read_data(self):
        print("讀取 JSON 檔案")
    
    def process_data(self):
        print("處理 JSON 資料")

# 使用範例
csv_processor = CSVProcessor()
csv_processor.process()
print("---")
json_processor = JSONProcessor()
json_processor.process()

10. 命令模式 (Command Pattern)

精神:將請求封裝成物件,讓你可以用不同的請求參數化客戶端。

白話解釋:像是遙控器的按鈕,每個按鈕都是一個命令,按下就執行對應動作。

常見用法:撤銷/重做功能、巨集錄製、佇列請求

class Light:
    def turn_on(self):
        return "燈光開啟"
    
    def turn_off(self):
        return "燈光關閉"

class LightOnCommand:
    def __init__(self, light):
        self.light = light
    
    def execute(self):
        return self.light.turn_on()
    
    def undo(self):
        return self.light.turn_off()

class LightOffCommand:
    def __init__(self, light):
        self.light = light
    
    def execute(self):
        return self.light.turn_off()
    
    def undo(self):
        return self.light.turn_on()

class RemoteControl:
    def __init__(self):
        self.command = None
        self.history = []
    
    def set_command(self, command):
        self.command = command
    
    def press_button(self):
        if self.command:
            result = self.command.execute()
            self.history.append(self.command)
            return result
    
    def press_undo(self):
        if self.history:
            last_command = self.history.pop()
            return last_command.undo()

# 使用範例
light = Light()
light_on = LightOnCommand(light)
light_off = LightOffCommand(light)

remote = RemoteControl()
remote.set_command(light_on)
print(remote.press_button())  # 燈光開啟
print(remote.press_undo())    # 燈光關閉

總結

設計模式的核心價值:

  • 提高程式碼的可重用性:相同的模式可以在不同專案中使用
  • 提高程式碼的可讀性:使用標準化的解決方案,團隊成員更容易理解
  • 降低耦合度:各個元件之間的依賴關係更加清晰
  • 提高可維護性:結構清晰的程式碼更容易修改和擴展

記住:設計模式不是萬能的,要根據實際需求選擇合適的模式,避免過度設計!