iT邦幫忙

2023 iThome 鐵人賽

DAY 9
0
自我挑戰組

Design Pattern - 無所不在的設計模式系列 第 9

[Day09] Design Pattern - Singleton

  • 分享至 

  • xImage
  •  

前言

今天要講設計模式中最為常見的Pattern!

定義


Singleton is a creational design pattern that lets you ensure that a class has only one instance, while providing a global access point to this instance.
-- Refactoring Guru

Singleton Pattern--單例模式
它限制了每一個class的初始化,並保證一個class裡只有一個instance可以被創建

我們先來看它的UML吧~

Singleton Pattern UML


Singleton class宣告了一個靜態方法getInstance,該方法返回其自身class的同一instance。

Singleton的建構子(constructor)應該對client端的code做隱藏。呼叫getInstance方法應該是獲得Singleton物件的唯一方式。

那Singleton是為了解決什麼問題出現的呢?


Singleton設計模式是為了解決以下主要問題而出現的:

  1. 當需要全域中唯一的Instance:
    在某些情況下,應用程式需要確保只有一個instance存在,以協調各種操作或資源的訪問。
    例如,當需要管理global的系統設定、資料庫的連接、儲存或讀取記錄時,這種需求變得非常重要。
    Singleton模式確保只有一個唯一的instance,這樣就可以和global共享或是訪問這個instance,而不需要重複創建或管理多個instances。

  2. 避免資源浪費:
    如果某個類別的instance在應用程式中多次創建,可能會導致資源浪費,例如記憶體。
    Singleton模式的延遲初始化特性確保instance只在需要時才被創建,從而減少了資源消耗。

  3. 確保唯一性:
    在某些情況下,需要確保某個物件的唯一性,以避免多個Instance導致不一致的狀態。
    Singleton模式可以確保只有一個instance存在,因此可以讓它維持一樣的狀態。

什麼情況下會使用到Singleton呢?


單例模式在以下情況會出現:

  • Unique Access Point: 當希望有個單一存取點來訪問一個instance時,單例模式提供了一個明確且可控的方式。
    若沒有單一訪問點會像下圖一樣~ 客戶端也許不會發現他們正在和同一個物件溝通

    -- 圖片來源: Refactoring Guru

  • 共享資源: 當系統的多個部分需要共享相同的資源(例如config data、loggin service或cache)時,單例確保它們都使用相同的instance,以維持一致性。

  • 狀態維護: 如果需要在多個consumer之間保持一致的狀態,單例可以通過 提供一個單一的具有狀態的instance來幫助實現。

  • 資源密集型物件: 當創建一個物件需要耗時、資源密集或僅需要初始化一次時,使用單例可以確保該物件只有被實例化一次並在之後重複使用。

  • 硬體訪問控制: 對於訪問硬體界面(如印表機、序列埠或任何需要控制和序列化訪問的設備)時。

  • 資料庫連接池: 單例模式可以管理資料庫連接池,確保有效重複使用連接並實現控制訪問。

  • (軟體)授權或配置檢查: 如果需要定期檢查軟體的授權或配置,單例可以確保檢查是集中化且一致的。

來個例子吧~


依照慣例,來舉一個例子吧~

假設今天一座城市裡只有1座機場,
機場裡雖然有好多不同的航空公司,
但一座城市裡只有一個機場,同時要確保所有航班的統一和安排

我們先來建一個機場單例

//singleton,確保整個城市只有一個機場實例
public class Airport
{
    private static Airport instance;
    private List<Flight> flights;

    // 建立機場的private constructor
    private Airport()
    {
        flights = new List<Flight>();
        Console.WriteLine("機場已建立!");
    }

    // 獲取機場實例的方法,使用Singleton模式確保唯一性
    public static Airport GetInstance()
    {
        if (instance == null)
        {
            instance = new Airport();
        }
        return instance;
    }

    // 添加航班到機場的航班列表
    public void AddFlight(Flight flight)
    {
        flights.Add(flight);
        Console.WriteLine($"新增航班 {flight.FlightNumber} 目的地:{flight.Destination}");
    }

    // 顯示所有已安排的航班
    public void DisplayFlights()
    {
        Console.WriteLine("=== 航班列表 ===");
        foreach (var flight in flights)
        {
            Console.WriteLine($"航班號:{flight.FlightNumber}, 目的地:{flight.Destination}");
        }
        Console.WriteLine("=================");
    }
}

航班資料的class

// 航班類別
public class Flight
{
    public string FlightNumber { get; set; }
    public string Destination { get; set; }

    public Flight(string flightNumber, string destination)
    {
        FlightNumber = flightNumber;
        Destination = destination;
    }
}

最後Main class,我們創建了一家機場實例,然後添加了兩個航班到機場的航班列表中,最後顯示了航班列表。
這確保了機場實例的唯一性,以及對所有航班的統一和安排,符合機場在城市中的唯一性的特性。

class Program
{
    static void Main()
    {
        // 獲取機場實例
        Airport airport = Airport.GetInstance();

        // 創建一些航班
        Flight flight1 = new Flight("FL123", "紐約");
        Flight flight2 = new Flight("FL456", "洛杉磯");

        // 添加航班到機場
        airport.AddFlight(flight1);
        airport.AddFlight(flight2);

        // 顯示所有航班
        airport.DisplayFlights();

        Console.ReadLine();
    }
}

上一篇
[Day08] Design Pattern - Abstract Factory抽象工廠模式
下一篇
[Day10] Design Pattern - Prototype 原型模式
系列文
Design Pattern - 無所不在的設計模式30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言