Archive

Archive for the ‘Design Patterns’ Category

Singleton “plus”, or yet another way to improve Singleton pattern

Có thể xem Singleton là một trong những mẫu thiết kế (Design Pattern) dễ cài đặt nhưng cũng rất hiệu quả trong thiết kế phần mềm. Ở đây không nhắc lại về mẫu này, chỉ xin trình bày một số “cải tiến” nhỏ đối với Singleton mà tác giả đã sử dụng cho phần mềm của mình trong thực tế.

1. Thread-safe Singleton objects

Mục đích: Mẫu Singleton chuẩn có thể sử dụng cho các lớp chỉ có duy nhất 1 instance trong chương trình. Tuy nhiên trong các ứng dụng có nhiều thread, mà các thread này đều phải truy xuất chung đến một đối tượng Singleton thì sẽ nảy sinh nguy cơ xung đột. Do đó cần có cơ chế đảm bảo việc truy xuất đối tượng Singleton sao cho không xảy ra hiện tượng này.

Cài đặt:

public class TSSingleton
{

private static object SyncRoot = new object();

private static TSSingleton m_Instance;

protected TSSingleton()
{

// Initialize code goes here…

}

public static TSSingleton Instance
{
get
{

lock(SyncRoot)
{
if(m_Instance == null)
m_Instance = new TSSingleton();
}
return m_Instance;
}
}

}

Cài đặt khá đơn giản. Một đối tượng SyncRoot được dùng để đảm bảo tại một thời điểm, chỉ có đúng 1 thread truy xuất đối tượng TSSingleton. Kĩ thuật này hiệu quả khi đối tượng Singleton là một phần tử trong giao diện, và có vài thread đang chạy nền có như cầu truy xuất đến nó.

2. “Multi”-ton

Ứng dụng thực tế: Các chương trình chat như Yahoo Messenger, Microsoft Live Messenger v.v… có thể quản lý nhiều cửa sổ chat cùng một lúc, nhưng mỗi cửa sổ là duy nhất cho một nick. Giả sử bạn đang chat với nick A, thì chỉ duy nhất 1 cửa sổ chat được tạo ra, ứng với nick chat này. Như vậy nảy sinh yêu cầu có một tập các đối tượng Singleton. Cài đặt cái này trong C# cũng không quá khó:

using System.Collections.Generic;

public class Multiton
{

private static Dictionary<string, Multiton> m_arrInstances = new Dictionary<string, Multiton>();

private readonly string m_sID;

protected Multiton(string sID)
{
m_sID = sID;
// Initialize code goes here…
}

public static GetInstance(string ID)
{
if(!m_arrInstances.ContainsKey(ID))
m_arrInstances[ID] = new Multiton(ID);

return m_arrInstances[ID];
}

}

Trong destructor của lớp, ta cần thêm vào câu lệnh:

m_arrInstances.Remove(m_sID);

để loại đối tượng này khỏi danh sách!