Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> C#

Private Constructors และ Singleton Pattern ใน C#

Private Constructor ใช้ป้องกันการสร้าง Instance จากภายนอก ใช้ใน:

  • Class ที่มีเฉพาะ Static Members (Utility Class)
  • Singleton Pattern
  • Factory Methods
  • Prevent Inheritance (sealed class + private constructor)

1. Static Class / Utility Class

public static class MathUtils {
    // Static class ไม่ต้องการ Constructor — Compiler กันการ Instantiate ให้
    public static double PI = 3.14159;
    public static int Add(int a, int b) => a + b;
}

หรือ Non-static Class ที่มีเฉพาะ Static Members:

public class Constants {
    private Constants() { } // Private Constructor — ป้องกัน new Constants()
    
    public static readonly string AppName = "MyApp";
    public static readonly int Version = 1;
}

2. Singleton Pattern

รับประกันว่ามี Instance เพียง 1 ตัวตลอด Lifetime ของ Application

รุ่นคลาสสิก (Thread-Safe ด้วย Lock)

public sealed class Singleton {
    private static Singleton _instance;
    private static readonly object _lock = new object();
    
    private Singleton() { } // Private Constructor
    
    public static Singleton Instance {
        get {
            if (_instance == null) {
                lock (_lock) {
                    if (_instance == null) {
                        _instance = new Singleton();
                    }
                }
            }
            return _instance;
        }
    }
    
    public void DoSomething() => Console.WriteLine("Singleton working!");
}

รุ่นสมัยใหม่ (Lazy<T> — Thread-Safe โดยอัตโนมัติ)

public sealed class Singleton {
    private static readonly Lazy _instance = 
        new Lazy(() => new Singleton());
    
    private Singleton() { }
    
    public static Singleton Instance => _instance.Value;
    
    public void DoSomething() => Console.WriteLine("Singleton working!");
}

รุ่น .NET 6+ (Thread-Safe, Lazy, Minimal)

public sealed class Singleton {
    private Singleton() { }
    
    public static Singleton Instance { get; } = new Singleton();
    
    public void DoSomething() => Console.WriteLine("Singleton working!");
}

Static Constructor ใน C# รับประกัน Thread-Safety และ Lazy Initialization อัตโนมัติ

การใช้งาน

Singleton.Instance.DoSomething();
// หรือ
var s = Singleton.Instance;

⚠️ ข้อควรพิจารณา

  • Singleton เป็น Anti-pattern ในบางบริบท — ทำให้ Unit Testing ยาก, Hidden Dependencies, Global State
  • พิจารณา Dependency Injection แทน (Register as Singleton ใน DI Container)
  • ถ้าต้องใช้ Singleton ให้ใช้ Lazy<T> หรือ Static Constructor รุ่นใหม่

สรุป

Patternใช้เมื่อ
Private Constructor + Static ClassUtility/Constants เท่านั้น
Singleton (Lazy<T>)ต้องการ Instance เดียว Global Access
Factory Methodควบคุมการสร้าง Instance (Validation, Pooling, Subclass Selection)
Dependency Injectionส่วนใหญ่ — Testable, Loose Coupling, Managed Lifetime