در ضمن حتما هم قرار نیست که با کلاس استاتیک پیاده بشه، کلاس استاتیک یک روش دیگر به پیاده کردن سینگلتن در سی شارپ اضافه میکنه و خیلی راه هایه دیگری هم هستند که سینگلتن را پیاده میکنند.
از این نظر مطمئن نیستم، چون به قول خودتون، شراط الگوی طراحی singleton رو باید تامین کنه، که به نظرم تامین نمیکنه.
کی این یکی کد را ترجیح میده به این یکی کد؟
معلومه، هیچکس
چون در حالت اول از الگوی طراحی singleton استفاده کرده ولی در حالت دوم، از یک متد استاتیک.
کلاس static خودش یک Global Point است.
بله، تاحدودی درسته ولی کلاس static اجازه دسترسی به نمونه ی شیئ رو نمیده و Global Point اش برای دیگر اشیاء قابل دسترسی نیست و فقط خودش میتونه ازش استفاده کنه).
لازم نیست که اشاره کنه، ترجمه a Global Access Point
یعنی اینکه که از همه جا بشه بهش دسترسی داسی.
معنی این دسترسی حتما اینکه باید بهش اشاره کرد نیست.
در کلاس استاتیک، میشه بطور غیر مستقیم به "نمونه" دسترسی داشت (یعنی اجازه دسترسی به نمونه رو از طریق دیگر اشیاء، نداریم و فقط توسط خود کلاس static میشه از نمونه استفاده کرد). اما متدی مثل ShowMessage که بعنوان یک کد ارائه کردید، یک Global Point نیست، بلکه یک متد Static است.
هدفی که یک الگوی طراحی singleton در نظر داره، اینه:
ensure a class has only one instance, and provide a global point of access to it
به تعریف فوق دقت کنیم متوجه میشیم که، منظور از it، همان خود "نمونه" از کلاس است یعنی معنیش به این شکل میشه:
"مطمئن شدن از اینکه هر کلاس فقط یک نمونه داره، و یک نقطه کلی برای دسترسی به آن، تامین شده باشه."
که منظور از "آن"، "نمونه" ی کلاس باید باشه. اما کلاس استاتیک، اجازه دسترسی به "نمونه" رو نمیده و برای دسترسی به "نمونه" ی کلاس، باید خود کلاس static رو مورد استفاده قرار بدیم.
در کلاس استاتیک، هدف اول تامین میشه، یعنی:
ensure a class has only one instance
اما در کلاس static هدف دوم تامین نمیشه، یعنی:
and provide a global point of access to it
+ پس طبق هدف اول، مطمئن هستیم که در کلاس استاتیک فقط یک نمونه شیئ وجود داره.
+ اما طبق هدف دوم، توسط کلاس static نمیشه یک Global Point رو برای نمونه شیئ تامین کرد و برای دسترسی به کلاس فقط یک Global Point وجود داره و آن خود کلاس static است. بگذارید این قسمت رو بیشتر بحث کنیم، منظور از اینکه کلاس استاتیک یک Global Point برای دسترسی به نمونه شیئ نداره، اینه که نمیتونیم توسط شیئ دیگری بغیر از خود کلاس static، از شیئ استفاده کنیم. مثلا کلاس static زیر رو در نظر بگیرید:
public static class A
{
public static string B()
{
return "none";
}
}
متد B یک عضو از نمونه شیئی است که توسط کلاس static میشه به اون شیئ دسترسی داشت و قاعدتا متد B رو صدا زد. اما بغیر از کلاس static، میشه توسط شیئ دیگری به آن نمونه دسترسی داشت و متد B رو صدا زد؟ میدونید که نمیشه.
اما کلاس زیر که طبق الگوی Singleton طراحی شده:
public class A
{
private A() {}
public static readonly A a = new A();
public string B()
{
return "none";
}
}
فرق کلاس فوق با کلاس قبلی در اینه که میشه توسط اشیاء دیگه، به نمونه شیئ دسترسی داشته، مثلا من توسط شیئ ccc میتونم به نمونه شیئ دسترسی داشته باشم و متد B رو اجرا کنم، اما در استاتیک فقط توسط خود کلاس static میشه به نمونه شیئ دسترسی داشت، مثلا در کلاس A که از الگوی طراحی singleton استفاده کرده، من میتونم از طریق شیئ ccc به نمونه (منظورم همون Instance است) دسترسی داشته باشم و متد B رو صدا بزنم، یعنی:
A ccc = A.a;
ccc.B();
و این یکی از نیازهای سینگلتن پترن بود و جمله زیر رو ارضا میکنه:
and provide a global point of access to it
پس تونستیم از طریق شیئ ccc به نمونه دسترسی داشته باشیم و متد B رو اجرا کنیم. ولی کلاس static چنین هدفی رو برآورده نمیکنه.
میشه یک شئی ایجاد کرد و به آن دسترسی داشت، روش ساده نوشتن یک مساج باکس در خود دات نت هم همین طوری است.
در خود دات نت، اعضای MessageBox بصورت static هستند، مثلا کدهای MessageBox بصورت زیر است (با نرم افزار Reflector):
public class MessageBox
{
// Fields
private const int HELP_BUTTON = 0x4000;
[ThreadStatic]
private static HelpInfo[] helpInfoTable;
private const int IDABORT = 3;
private const int IDCANCEL = 2;
private const int IDIGNORE = 5;
private const int IDNO = 7;
private const int IDOK = 1;
private const int IDRETRY = 4;
private const int IDYES = 6;
// Methods
private MessageBox();
private static void PopHelpInfo();
private static void PushHelpInfo(HelpInfo hpi);
public static DialogResult Show(string text);
public static DialogResult Show(string text, string caption);
public static DialogResult Show(IWin32Window owner, string text);
public static DialogResult Show(string text, string caption, MessageBoxButtons buttons);
public static DialogResult Show(IWin32Window owner, string text, string caption);
public static DialogResult Show(string text, string caption, MessageBoxButtons buttons, MessageBoxIcon icon);
public static DialogResult Show(IWin32Window owner, string text, string caption, MessageBoxButtons buttons);
public static DialogResult Show(string text, string caption, MessageBoxButtons buttons, MessageBoxIcon icon, MessageBoxDefaultButton defaultButton);
public static DialogResult Show(IWin32Window owner, string text, string caption, MessageBoxButtons buttons, MessageBoxIcon icon);
public static DialogResult Show(string text, string caption, MessageBoxButtons buttons, MessageBoxIcon icon, MessageBoxDefaultButton defaultButton, MessageBoxOptions options);
public static DialogResult Show(IWin32Window owner, string text, string caption, MessageBoxButtons buttons, MessageBoxIcon icon, MessageBoxDefaultButton defaultButton);
public static DialogResult Show(string text, string caption, MessageBoxButtons buttons, MessageBoxIcon icon, MessageBoxDefaultButton defaultButton, MessageBoxOptions options, bool displayHelpButton);
public static DialogResult Show(string text, string caption, MessageBoxButtons buttons, MessageBoxIcon icon, MessageBoxDefaultButton defaultButton, MessageBoxOptions options, string helpFilePath);
public static DialogResult Show(IWin32Window owner, string text, string caption, MessageBoxButtons buttons, MessageBoxIcon icon, MessageBoxDefaultButton defaultButton, MessageBoxOptions options);
public static DialogResult Show(string text, string caption, MessageBoxButtons buttons, MessageBoxIcon icon, MessageBoxDefaultButton defaultButton, MessageBoxOptions options, string helpFilePath, string keyword);
public static DialogResult Show(string text, string caption, MessageBoxButtons buttons, MessageBoxIcon icon, MessageBoxDefaultButton defaultButton, MessageBoxOptions options, string helpFilePath, HelpNavigator navigator);
public static DialogResult Show(IWin32Window owner, string text, string caption, MessageBoxButtons buttons, MessageBoxIcon icon, MessageBoxDefaultButton defaultButton, MessageBoxOptions options, string helpFilePath);
public static DialogResult Show(string text, string caption, MessageBoxButtons buttons, MessageBoxIcon icon, MessageBoxDefaultButton defaultButton, MessageBoxOptions options, string helpFilePath, HelpNavigator navigator, object param);
public static DialogResult Show(IWin32Window owner, string text, string caption, MessageBoxButtons buttons, MessageBoxIcon icon, MessageBoxDefaultButton defaultButton, MessageBoxOptions options, string helpFilePath, string keyword);
public static DialogResult Show(IWin32Window owner, string text, string caption, MessageBoxButtons buttons, MessageBoxIcon icon, MessageBoxDefaultButton defaultButton, MessageBoxOptions options, string helpFilePath, HelpNavigator navigator);
public static DialogResult Show(IWin32Window owner, string text, string caption, MessageBoxButtons buttons, MessageBoxIcon icon, MessageBoxDefaultButton defaultButton, MessageBoxOptions options, string helpFilePath, HelpNavigator navigator, object param);
private static DialogResult ShowCore(IWin32Window owner, string text, string caption, MessageBoxButtons buttons, MessageBoxIcon icon, MessageBoxDefaultButton defaultButton, MessageBoxOptions options, bool showHelp);
private static DialogResult ShowCore(IWin32Window owner, string text, string caption, MessageBoxButtons buttons, MessageBoxIcon icon, MessageBoxDefaultButton defaultButton, MessageBoxOptions options, HelpInfo hpi);
private static DialogResult Win32ToDialogResult(int value);
// Properties
internal static HelpInfo HelpInfo { get; }
}
تمام اعضا استاتیک است (بغیر از متد سازنده) که در متد Show هم از یک عضو private و static ای بنام ShowCore استفاده شده. چون در حالتی که از متد یا اعضای static استفاده میکنیم، این متدها یا اعضا به همان نمونه شیئ ای تعلق دارند که استاتیک است یعنی برای دسترسی به این متدها و اعضا (که استاتیک هستند)، فقط و فقط خود کلاس میتونه دسترسی داشته باشه. وقتی که یک اعضا استاتیک باشه و متد سازنده هم private باشه، تقریبا مثل یک کلاس static عمل میکنه و طبق مطالبی که در بالا نوشته بودم، کلاس استاتیک با الگوی طراحی singleton فرق میکنه.
لازم نیست که معنی دسترسی (Access) حتما داشتن یک اشاره به شئی باشه، بلکه داشتن کنترل بر کارهایی که شئی میواند انجام بدهد هم حساب میش
طبق اون مطالبی که در بالا نوشتم، منظورش همان خود "نمونه" ی شیئ است. چون در هدف (قسمت) اول از تعریف گفته که "only one instance" و در هدف (قسمت) دوم گفته که "access to it"، پس منظور از it باید همان one instance (تنها نمونه) باشه.
من یک مثال ساده ضمیمه کردم که کد اصلیش این است
ممنون، مثال خوبی بود و استفاده از این روش برای MessageBox خیلی مناسبه (روش خیلی جالبی بود).
در کدهایی که نوشتید، کلاس MEssageBox هدف اول یعنی Only one instance رو تحقق می بخشه ولی هدف دوم یعنی global point of access to it را برآورده نمیکنه.
یک کم دیگه منظورم رو بهتر برسونم که منظور از global point of access to it حتما باید نمونه شیئ باشه. چون مثلا وقتی که از یک کلاس static استفاده میکنیم، فقط و فقط کلاس static میتونه به نمونه خودش دسترسی داشته باشه، پس برای دسترسی به نمونه شیئ یک کلاس استاتیک، حتما باید از نام خود کلاس static استفاده کنیم، چون به هیچ وجه به نمونه (One Instance) دسترسی نداریم، بلکه کلاس static به آن دسترسی داره.
اما وقتی که از الگوی طراحی singleton استفاده میشه، توسط این الگو، نمونه شیئ (منظورم همان one instance) رو بعنوان یک فیلد یا مقدار برگشتی یک متد، مورد دسترسی دیگر کلاسها قرار میده و کلاس مثلا همون ccc میتونه بهش دسترسی داشته باشه، درصورتی که در کلاس static، فقط کلاس استاتیک میتونه دسترسی داشته باشه.
انشاالله بعد از اینکه این بحث سینگلتن به نتیجه رسید بریم سراغه بقیه الگوها :)
انشاالله اگر خدا بخواد، با هم (together) بقیه الگوها هم میبریم زیر ذره بین
متاسفانه من از امشب تا یک هفته بعد (12 مرداد) نمیتونم به این فروم بیام و به اینترنت وصل بشم، اما بعد از گذشت یک هفته، دوباره به سایت میام و پاسخ های شما رو نگاه میکنم.
امیدوارم که اگر پاسخی داشتید یا مطلبی رو لازم دونستید رو بنویسید تا من یک هفته بعد بیام و بحث رو از سر بگیریم تا با رد و بدل کردن صحبت ها، به نتایج لازم برسیم.
امیدوارم که اگر لازم بود، بحث ادامه پیدا کنه.