فکر میکنم اکثر دوستان با این pattern آشنا باشند.
(اونایی که از این الگو اطلاعی ندارن به این لینک مراجعه کنند :
http://www.dofactory.com/Patterns/PatternSingleton.aspx)
اما بصورت خیلی خلاصه : در این الگو هدف رسیدن به وضعیتی است که بتونیم تضمین کنیم از یک کلاس فقط و فقط یک (و یا در حالتی خاص: تعدادی مشخص و کنترل شده) آبجکت ساخته شود. (ضمن اینکه روش مناسبی برای عملیاتی ست که نیاز به یک دسترسی سراسری دارند)
Ensure a class has only one instance and provide a global point of access to it
.
استفاده از این الگو در موارد بسیاری از جمله ConnectionManager و یا در همین موضوع کنترل فرمها بصورتی که از هر فرم تنها یک Instance ساخته شود.
خب از اونجا که هدف تاپیک چیز دیگریست بحث راجع به این pattern رو همینجا خاتمه میدم.
در این پست سعی داریم یک برنامه بسازیم که متشکل از یک فرم والد و سه فرم فرزند باشه.
(و با این شرط که : فرم والد تنها میتواند یک نمونه از هر فرزند را در حافظه بار کند.)
اولن کاری که بنظر میرسه اینه که در تک تک فرمهای فرزند الگوی سینگلتون رو - مانند نمونه ی زیر - تکرار کنیم :
namespace Ticket
{
public partial class frmBoat : Form
{
#region Singleton Form
private static frmBoat formInstance = null;
public static frmBoat GetInstance()
{
if (formInstance == null)
{
formInstance = new frmBoat();
}
return formInstance;
}
private frmBoat()
{
InitializeComponent();
}
#endregion
}
}
البته راههای زیادی - و با توجه به حالتهای خاص - برای ایجاد کلاسهای سینگتون وجود دارد.
اما مشکل عمده ای که روش بالا دارد این است که باید برای تمامی فرمها (و یا بصورت کلی : برای تمامی کلاسهای مورد نظر) این الگو را تکرار کنیم.
چه خوب بود اگه میتونستیم یکبار این الگو رو مینوشتیم و همه جا از اون استفاده میکردیم.
لذا بدون مقدمه میریم سراغ نوشتن یک Generic Singleton :
public class SingletonProvider<T> where T : new()
{
SingletonProvider() { }
public static T Instance
{
get { return SingletonCreator.Instance; }
}
class SingletonCreator
{
private SingletonCreator() { }
private static T instance;
internal static T Instance
{
get
{
if (instance == null)
instance = new T();
else if (instance is Form)
if ((instance as Form).IsDisposed)
instance = new T();
return instance;
}
}
}
}
واقعا چقدر استفاده از کلاسهای ژنریک لذت بخشه. اینطور نیست ؟!
و کلاسی رو نیز به این شکل مینویسیم برای کنترل فرمهای فرزند :
public class FormManagementHelper
{
public static Form ShowChildForm(Form _parent, Form _child)
{
_child.MdiParent = _parent;
_child.Show();
_child.Activate();
return _child;
}
public static void ShowChild1(Form _parent)
{
ShowChildForm(_parent, SingletonProvider<Child1>.Instance);
}
public static void ShowChild2(Form _parent)
{
ShowChildForm(_parent, SingletonProvider<Child2>.Instance);
}
public static void ShowChild3(Form _parent)
{
ShowChildForm(_parent, SingletonProvider<Child3>.Instance);
}
}
خب فکر میکنم خود کد به تنهایی گویا باشه.
فقط اینکه Child1 , Child2, Child3 اسم فرمهای فرزند هستند که توسط کلاس ژنریک سینگلتون یک Instance از اونها برگشت داده میشه.
و در ادامه در کد فرم والد این کدها رو برای نشون دادن فرمهای فرزند مینویسیم :
private void child1ToolStripMenuItem_Click(object sender, EventArgs e)
{
FormManagementHelper.ShowChild1(this);
}
private void child2ToolStripMenuItem_Click(object sender, EventArgs e)
{
FormManagementHelper.ShowChild2(this);
}
private void child3ToolStripMenuItem_Click(object sender, EventArgs e)
{
FormManagementHelper.ShowChild3(this);
}