#6 – 什麼是 設計模式 (design pattern) ?

設計模式簡介

設計模式(Design Pattern)是解決常見程式設計問題的通用方案。
它不是程式碼本身,而是一種指導如何編寫程式碼的方式。


設計模式分為三大類:

  1. 創建型模式(Creational Patterns)
  2. 結構型模式(Structural Patterns)
  3. 行為型模式(Behavioral Patterns)
類型目的範例
創建型模式解決如何建立物件的問題,提供更好的方式來建立和管理物件。單例模式(Singleton)、工廠模式(Factory)
結構型模式關注類與物件之間的組合,確保系統結構靈活且易於擴展。裝飾器模式(Decorator)、代理模式(Proxy)
行為型模式處理類或物件之間的責任分配及通訊協作,定義如何進行互動。觀察者模式(Observer)、命令模式(Command)

簡單實例解釋

1. 單例模式(Singleton Pattern)

確保某個類別只有一個實例,並提供全域存取點。

適用場景

  • 資料庫連線物件。
  • 設定檔管理器。
public class Singleton
{
    private static Singleton _instance;

    // 私有建構子,防止外部實例化
    private Singleton() { }

    // 提供全域存取的靜態方法
    public static Singleton Instance
    {
        get
        {
            if (_instance == null)
            {
                _instance = new Singleton();
            }
            return _instance;
        }
    }

    public void DoSomething()
    {
        Console.WriteLine("單例模式運行中...");
    }
}

// 測試
public class Program
{
    public static void Main()
    {
        Singleton instance1 = Singleton.Instance;
        Singleton instance2 = Singleton.Instance;

        Console.WriteLine(instance1 == instance2); // True
        instance1.DoSomething();
    }
}

2. 工廠模式(Factory Pattern)

定義一個用於創建物件的介面,而讓子類決定要實例化哪個類別。工廠方法將物件創建的細節與使用者分離。

適用場景

  • 根據條件建立不同類型的物件。
  • 例如:支付系統中,建立不同的付款方式(信用卡、PayPal)。
// 付款方式介面
public interface IPayment
{
    void Pay(decimal amount);
}

// 信用卡付款實現
public class CreditCardPayment : IPayment
{
    public void Pay(decimal amount)
    {
        Console.WriteLine($"使用信用卡付款: {amount} 元");
    }
}

// PayPal 付款實現
public class PayPalPayment : IPayment
{
    public void Pay(decimal amount)
    {
        Console.WriteLine($"使用 PayPal 付款: {amount} 元");
    }
}

// 工廠類別
public class PaymentFactory
{
    public static IPayment CreatePayment(string type)
    {
        return type switch
        {
            "CreditCard" => new CreditCardPayment(),
            "PayPal" => new PayPalPayment(),
            _ => throw new ArgumentException("不支援的付款方式")
        };
    }
}

// 測試
public class Program
{
    public static void Main()
    {
        IPayment payment = PaymentFactory.CreatePayment("CreditCard");
        payment.Pay(1000);

        payment = PaymentFactory.CreatePayment("PayPal");
        payment.Pay(500);
    }
}

3. 觀察者模式(Observer Pattern)

定義一種一對多的依賴關係,當一個物件的狀態改變時,所有依賴它的物件都會自動收到通知並更新。

適用場景

  • 訂閱通知系統(如新聞推播、股票價格變化)。
// 觀察者介面
public interface IObserver
{
    void Update(string message);
}

// 主題類別(被觀察者)
public class Subject
{
    private readonly List<IObserver> _observers = new();

    public void AddObserver(IObserver observer)
    {
        _observers.Add(observer);
    }

    public void RemoveObserver(IObserver observer)
    {
        _observers.Remove(observer);
    }

    public void NotifyObservers(string message)
    {
        foreach (var observer in _observers)
        {
            observer.Update(message);
        }
    }
}

// 具體觀察者
public class User : IObserver
{
    private readonly string _name;

    public User(string name)
    {
        _name = name;
    }

    public void Update(string message)
    {
        Console.WriteLine($"{_name} 收到通知: {message}");
    }
}

// 測試
public class Program
{
    public static void Main()
    {
        Subject subject = new();

        User user1 = new("Alice");
        User user2 = new("Bob");

        subject.AddObserver(user1);
        subject.AddObserver(user2);

        subject.NotifyObservers("有新的消息發布!");

        subject.RemoveObserver(user1);
        subject.NotifyObservers("只有 Bob 會收到這條消息。");
    }
}

如何選擇設計模式?

  1. 創建型模式
  • 如果需要靈活建立物件,例如根據不同條件建立不同類型的物件。
  • 範例:工廠模式。
  1. 結構型模式
  • 如果需要解決物件與物件之間的組合問題,例如新增功能時不影響核心邏輯。
  • 範例:裝飾器模式。
  1. 行為型模式
  • 如果需要管理物件之間的互動或流程,例如事件通知或執行順序。
  • 範例:觀察者模式。

學習與實踐建議

  1. 從問題出發
  • 思考實際開發中遇到的問題,選擇適合的模式。
  1. 閱讀經典書籍
  • 《設計模式:可復用面向物件軟體的基礎》(Design Patterns: Elements of Reusable Object-Oriented Software)。
  1. 動手實作
  • 嘗試用每個設計模式解決簡單的實際問題,加深理解。

結論

設計模式不是硬性規範,而是幫助我們解決常見問題的「工具箱」。靈活選擇模式,將能有效提升程式碼的品質與維護性!