Singleton design pattern
Singleton design pattern รูปแบบการออกแบบ class ในความต้องการที่ว่า เราอยาก ให้มีการสร้าง instance ของ class เพียง instance เดียวตลอดการทำงานของโปรแกรม ซึ่งผู้เรียกใช้สามารถเข้าถึงได้ผ่านทาง global access point หรือจุดที่เข้าถึง ที่เป็น global
สำหรับตัวอย่างการใช้งานของ pattern นี่นั้นเรามักจะใช้กับ ส่วนที่ต้องการให้มีเพียงหนึ่งเดียว เช่น file system หรือ windows manager เป็นต้น
โครงส้รางของ Singleton design pattern
จากโครงส้รางของ singleton design pattern เราจะเห็นว่า class ที่เป็น singleton นั้นเราจะให้มีการ ส้ราง instance ของตัวเอง ผ่านทาง Method ที่ชื่อว่า Instance() เพื่อให้เข้าใจง่ายขึ้นเราลองมาดูที่ code ตัวอย่างกันครับ
// Singleton class implements that simplest version of the Singleton
// design pattern.
//
public sealed class Singleton
{
private static readonly Singleton _instance = new Singleton();
// make the default constructor private, so that no can directly create it.
private Singleton()
{
}
// public property that can only get the single instance of this class.
public static Singleton Instance
{
get
{
return _instance;
}
}
}
<< ตัวอย่าง code จาก Design Pattern: Singleton in C# เขียนโดย Pedro Silva (darthpedro99@hotmail.com) >>
จาก code เราจะเห็นว่า class นั้นจะถูกกำหนด ให้เป็น seal class ก็คือจะไม่ได้มีการ inmplement class หรือ สืบทอด class นี้ ต่อไปเราจะพบว่า ตัวแปรที่ชื่อว่า instance นั้นเป็นตัวแปรที่ ชี้ไปยัง instance ของ class ครับ และมันถูกกำหนดให้เป็น stactic ทำให้มัน ถูกสร้างขึ้นมาครั้งเดียว หรือ instance เดียว เมื่อมีการ access ครั้งแรกเท่านั้น สำหรับการ access ครั้งต่อไป มันก็จะ ให้ instance เดิมครับ และมันถูกกำหนดให้เป็น readonly ไม่สามารถเปลี่ยนหรือแก้ไข ใด ๆ นะครับ
อีกอย่างที่สำคัญคือ หากต้องการที่จะได้ instance ของ class นี้นั้นจะต้อง access ผ่านทาง properties (หรือ method ) ที่ชื่อว่า Instance ซึ่งเป็นจุดเดียวที่ อนุญาติให้เข้าถึง instance ของ object นี้
ลองมาดูตัวอย่าง การใช้งานจริงกัน นะครับ
// singleton class
//----------------------------------------------
public sealed class LoadBalancer
{
private static readonly LoadBalancer _instance;
private List<string> _servers = new List<string>();
private Random _random = new Random();
// Lock synchronization object
private static object syncLock = new object();
// Constructor (protected)
protected LoadBalancer()
{
// List of available servers
_servers.Add("ServerI");
_servers.Add("ServerII");
_servers.Add("ServerIII");
_servers.Add("ServerIV");
_servers.Add("ServerV");
}
public static LoadBalancer GetLoadBalancer()
{
// Support multithreaded applications through
// 'Double checked locking' pattern which (once
// the instance exists) avoids locking each
// time the method is invoked
if (_instance == null)
{
lock (syncLock)
{
if (_instance == null)
{
_instance = new LoadBalancer();
}
}
}
return _instance;
}
// Simple, but effective random load balancer
public string Server
{
get
{
int r = _random.Next(_servers.Count);
return _servers[r].ToString();
}
}
}
เป็น class สำหรับ ทำ random เพื่อจ่ายการทำงาน ให้กับ server โดย instance ของ class จะ access ได้ผ่านท่าง GetLoadBalancer() ครับ
ข้อสังเกตุ นะครับ สำหรับการใส่ lock(syncLock) ไว้ก่อนการสร้าง instance เป็นการ ทำเพื่อให้สามารถนำ code นี้ไปใช้ในกรณี ที่มีหลาย thread ครับ
ดูตัวอย่างของการใช้ class นี่นะครับ
class MainApp
{
// <summary>
// Entry point into console application.
// </summary>
static void Main()
{
LoadBalancer b1 = LoadBalancer.GetLoadBalancer();
LoadBalancer b2 = LoadBalancer.GetLoadBalancer();
LoadBalancer b3 = LoadBalancer.GetLoadBalancer();
LoadBalancer b4 = LoadBalancer.GetLoadBalancer();
// Same instance?
if (b1 == b2 &amp;amp;amp;amp;&amp;amp;amp;amp; b2 == b3 &amp;amp;amp;amp;&amp;amp;amp;amp; b3 == b4)
{
Console.WriteLine("Same instance\n");
}
// Load balance 15 server requests
LoadBalancer balancer = LoadBalancer.GetLoadBalancer();
for (int i = 0; i < 15; i++)
{
string server = balancer.Server;
Console.WriteLine("Dispatch Request to: " + server);
}
// Wait for user
Console.ReadKey();
}
}
จะเห็น ว่าการเรียกใช้ เรานะทดสอบ การทำงานของ class ด้วยการส้ราง LoadBalance b1 , b2, b3, b4 เพื่อทดสอบว่า ทั้งหมดเป็น instance เดียวกัน
instance ของ class LoadBalancer จะถูกสร้าง ครั้งแรกครั้งเดียว เมื่อเรากำหนดค่าให้กับ b1
ในส่วนที่สองเป็นการ ทดสอบว่า มีการจ่ายงานให้กับ server หรือไม่อย่างไร
คงพอเข้าใจนะครับ เป็น การสร้างและทดสอบ การทำงาน singleton design pattern
คงพอที่ได้ แนวคิดในการใช้งาน นะครับ สำหรับ thread safe นั้นหากต้องการดูเพิ่มเติม ได้ที่ Design Pattern: Singleton in C#
ธีระพงษ์ สนธยามาลย์ Soft Speed Solution ’s senior programmer s_teearpong2000@yahoo.com