PDA

View Full Version : استفاده از فرم برنامه دیگر



HAIdle
سه شنبه 30 مرداد 1386, 13:04 عصر
با سلام
من یه فرم بعنوان messageBox فارسی طراحی کرده ام. حالا می خوام این فرم را مثل messageBox معمولی به کار بگیرم. یعنی لازم نباشه هر مرتبه این فرم را در پروژه ام وارد کنم ولی بتونم از اون استفاده کنم. لطفا راهنمایی کنید.(آیا باید بهdll تبدیلش کنم یا راه دیگه ای را باید پیش بگیرم. اگه باید بهdll تبدیلش کنم چه جوری باید این کار را بکنم؟)

PC2st
سه شنبه 30 مرداد 1386, 13:14 عصر
messagebox رو بصورت Static تعریف کنید یا اینکه به شیوه Singleton Design Pattern طراحیش کنید.

HAIdle
سه شنبه 30 مرداد 1386, 15:07 عصر
میشه بیشتر توضیح بدید؟

hdv212
سه شنبه 30 مرداد 1386, 15:23 عصر
اگه شما این فرم رو در پروژه های دیگه طراحی کردید و میخواهید در پروژه ی جاریتون ازش استفاده کنید. کافیه روی solution تون در solution explorer کلیلک راست کنید و گزینه ی add existing item رو انتخاب کنید و فرم مورد نظرتون رو (که با پسوند cs) هست رو انتخاب کنید و ok کنید. حالا هر جای کدتون که خواستید از این فرم آبجکت بسازید و استفاده کنید بایستی فضای نام پروژه ی قبلی ای که این فرم رو در اونجا ساختید ذکر کنید(میتونید از using استفاده کنید).

PC2st
سه شنبه 30 مرداد 1386, 15:46 عصر
اگر میخواید که message box تون مثل MessageBox در دات نت باشه یعنی احتیاج به نمونه سازی از روی آن نباشه و مسقیما از یک متد سریع استفاده کنید، باید یا اون رو Static تعریف کنید یا از الگوی طراحی Singleton پیروی کنید. اما فکر کنم منظور شما این نبوده (الان که یکبار دیگه با دقت پست رو مرور کردم)، بهر حال اگر منظورتون این بود، بهم بگید تا این رو توضیح بدم.

و منظورتون اینه که کدهایی که برای message box نوشتید رو در هر پروژه ای کپی و Paste نکنید، و همانطور که خودتون گفتید، dll چاره سازه. (البته اگه message box رو در یک فایل cs مینوشتید، فقط باید اون فایل رو توی پروژه کپی و Paste کنید)...

برای تبدیل به dll ابتدا کدهای کلاسی که مربوط به message box تون هست رو در کلیپ بورد کپی کنید، سپس از منوی File گزینه New Project رو انتخاب کرده و نوع Class Library را انتخاب کرده، یک نام (namespace) برای آن اختیار کنید و روی OK کلیک کنید، حال فقط کافیست که کدهای کلاسی که نوشته اید را بجای کدهای زیر، replace کرده و Paste شون کنید:


public class Class1
{
}

در اینصورت کدهای کلاس message box بجای اون کلاس قرار میگیره، حال کافیست که برنامه را در حالت Release با کلید F5 کامپایل کنید.
این فایل در پوشه bin\release ایجاد میشه، فایل dll ایجاد شد.

برای استفاده از فایل، به پروژه ای که میخواید از این dll استفاده کنید رفته و از Solution Explorer روی نام پروژه کلیک راست کنید و گزینه Add Reference رو انتخاب نمائید. از آنجا روی زبانه Browse کلیک کرده و فایل dll رو بهش بدید.

جایی که خواستید از message box تون استفاده کنید، ابتدا فضای نام آنرا از طریق using معرفی کرده (اختیاری) و سپس میتوانید از کلاستون استفاده کنید.
امیدوارم واضح گفته باشم.

mina1363
سه شنبه 30 مرداد 1386, 18:16 عصر
[quote=PC2st.ir;383549]اگر میخواید که message box تون مثل MessageBox در دات نت باشه یعنی احتیاج به نمونه سازی از روی آن نباشه و مسقیما از یک متد سریع استفاده کنید، باید یا اون رو Static تعریف کنید یا از الگوی طراحی Singleton پیروی کنید. اما فکر کنم منظور شما این نبوده (الان که یکبار دیگه با دقت پست رو مرور کردم)، بهر حال اگر منظورتون این بود، بهم بگید تا این رو توضیح بدم.

بله اگه ممکنه این رو برای من توضیح بدهید

PC2st
سه شنبه 30 مرداد 1386, 20:04 عصر
کلاس زیر رو در نظر بگیرید:


public static class MyMessageBox
{
private static Form messageBox = new Form();
private static Label textLabel = new Label();
private static Button okButton = new Button();
private static int _Padding = 10;
public static int Padding
{
get { return _Padding; }
set { _Padding = value; }
}
private static Size _Size;
public static Size Size
{
get { return _Size; }
set { _Size = value; }
}
static MyMessageBox()
{
Padding = 10;
Size = new Size(300, 200);
messageBox.FormBorderStyle = FormBorderStyle.FixedSingle;
messageBox.MaximizeBox = false;
messageBox.MinimizeBox = false;
messageBox.ShowIcon = false;
messageBox.StartPosition = FormStartPosition.CenterParent;
textLabel.AutoSize = false;
textLabel.BorderStyle = BorderStyle.FixedSingle;
okButton.Text = "OK";
okButton.DialogResult = DialogResult.OK;
messageBox.Controls.AddRange(new Control[] { textLabel, okButton });
}
public static DialogResult Show(string text, string title)
{
messageBox.Size = Size;
textLabel.Location = new Point(Padding, Padding);
textLabel.Size = new Size(messageBox.ClientSize.Width - 2 * Padding, messageBox.ClientSize.Height - okButton.Height - 2 * Padding);
okButton.Location = new Point(messageBox.ClientSize.Width - okButton.Width - Padding, messageBox.ClientSize.Height - okButton.Height - Padding);
messageBox.Text = title;
textLabel.Text = text;
return messageBox.ShowDialog();
}
}

کلاس فوق یک کلاس استاتیک است که هیچ نمونه ای نمیشه از روی آن ساخت یا حتی از آن ارث بری کرد. برای استفاده از آن هم لازم نیست که شیئی از روی آن ساخته بشه. تمام اعضای آن هم باید Static باشد. دارای یک سازنده هم هست که این سازنده از قبل اجرا میشه و نیازی به صدا زدن این سازنده نیست، چون خودش (اتوماتیک) اجرا میشه.
مثلا برای استفاده از کلاس فوق:


MyMessageBox("HHHHHHHHHHHHHHHH", "Title");

کلاس MyMessageBox دارای خواص استاتیک هم هست مثل Size و Padding، قبل از صدا زدن متد Show میتوان این خواص را مقدار دهی کرد تا در نحوه نمایش MyMessageBox تاثیر گذار باشند، مثلا:


MyMessageBox.Size = new Size(400, 400);
MyMessageBox.Padding = 25;
MyMessageBox.Show("Hello to C# world.", "About");


Singleton Pattern هم تقریبا مثل همین هست با این تفاوت که میشه message box رو بصورت یک پارامتر به متدها هم پاس دارد، ولی با این حال فقط یک نمونه از آن وجود داشته باشه.

mina1363
سه شنبه 30 مرداد 1386, 20:55 عصر
اگر بخواهیم روی این messageBox تصویر هم داشته باشیم چی ؟

PC2st
سه شنبه 30 مرداد 1386, 21:20 عصر
اگر بخوایم تصویر داشته باشه باید یک PictureBox بعنوان فیلد در آن تعریف کرد و کنترلش رو هم به شیئ messageBox اضافه کرد و خاصیت Size و Location و ... هم تنظیم کرد، مثل شیئ textlabel یا okButton.

mina1363
سه شنبه 30 مرداد 1386, 22:41 عصر
آره ولی باید بگم :
message. چی؟
چون هر کاری میکنم picturebox را که تعریف کردم نمیشناسه

PC2st
سه شنبه 30 مرداد 1386, 23:25 عصر
در قسمت فیلدها یک فیلد از نوع PictureBox تعریف کنید.


private static PictureBox ovwPictureBox = new PictureBox();


بعدش در متد MyMessageBox خصوصیاتش رو تنظیم کنید، مثلا:


ovwPictureBox.Size = new Size(32, 32);
ovwPictureBox.SizeMode = PictureBoxSizeMode.StretchImage;
messageBox.Controls.Add(ovwPictureBox);

در کد فوق که از متد Controls.Add استفاده کردم، فقط حواستون باشه که این متد را قبل از متدی قرار بدید که کنترلهای textLabel و okButton اضافه شدند، یعنی مثل زیر باید باشه:


messageBox.Controls.Add(ovwPictureBox);
messageBox.Controls.AddRange(new Control[] { textLabel, okButton });

که همانطور که پر رنگش کردم باید قبل از کنترلهای قبلی به فرم اضافه بشه وگر نه عکس رو نمیتونید ببینید چون پشت کنترل textLabel میافته.

بعدش در متد Show اندازه و موقعیت اون رو تنظیم کنید، مثلا چون خواستیم اندازه ovwPictureBox ثابت باشه (32x32) پس اندازه اون رو در متد MyMessageBox مشخص کردیم ولی چون موقعیت ovwPictureBox ثابت نیست، پس موقعیت اون رو در متد Show تنظیم میکنیم، که بر اساس مقدار خاصیت Padding این تنظیم صورت میگیره، مثلا در متد Show این رو مینویسیم:


ovwPictureBox.Location = new Point(messageBox.ClientSize.Width - ovwPictureBox.Width - Padding, Padding);


فقط باید یک خاصیت به کلاس MyMessgaeBox هم اضافه بشه که کاربر بتونه یک عکس رو براش مشخص کنه:


public static Image Image
{
get { return ovwPictureBox.Image; }
set { ovwPictureBox.Image = value; }
}

تمام شد. فقط یک چیزی که هست، اگر متن نمایشی زیاد باشه، پشت عکس میافته، باید برای این هم تنظیم بشه و ... قسمت های تکمیلیش به عهده خودتون :بامزه:

mina1363
چهارشنبه 31 مرداد 1386, 12:51 عصر
خیلی ممنون خستتون کردم انقدر سؤال پرسیدم دیگه؟

PC2st
چهارشنبه 31 مرداد 1386, 13:01 عصر
خیلی ممنون خستتون کردم انقدر سؤال پرسیدم دیگه؟
اختیار دارید، من خوشحال میشم که سوالی پرسیده بشه و من بتوانم جواب بدم.

اَرژنگ
پنج شنبه 01 شهریور 1386, 07:10 صبح
کلاس زیر رو در نظر بگیرید:
[code]
public static class MyMessageBox
.
.
.

دلیل استفاده از استاتیک چی هست؟
شما که از استفاده از سینگلتن آگاهی دارید و میدانید که از نظر برنامه نویسی شئیگرایی درست است، روش استفاده از سینگلتن را نشانشان بدید.
این روشهایی که از استاتیک استفاده میکنند فرقی با برنامه نویسی قدیمی غیر شئیگرا ندارند.

PC2st
پنج شنبه 01 شهریور 1386, 12:07 عصر
دلیل استفاده از استاتیک چی هست؟
شما که از استفاده از سینگلتن آگاهی دارید و میدانید که از نظر برنامه نویسی شئیگرایی درست است، روش استفاده از سینگلتن را نشانشان بدید.
این روشهایی که از استاتیک استفاده میکنند فرقی با برنامه نویسی قدیمی غیر شئیگرا ندارند.
راستش به یک دلیل static رو به جای Singleton Pattern انتخاب میکنیم، به دلیل اینکه اشیائی که static هستند، نمیشه ارجاعهای مختلفی به آن شیئ static داشت. ولی طبق قاعده Singleton Pattern، شیئی خواهیم داشت که فقط یک نمونه از اون وجود داشته باشه (مثل static) ولی از طریق ارجاعهای مختلف، بشه به اون شیئ دسترسی داشت (برخلاف static). مثلا اگر همین کلاس MyMessageBox رو به شیوه سینگلتن طراحی میکردیم، به شکلهای زیر میشد ازش استفاده کرد:


MyMessageBox mmsg1 = MyMessageBox.GetInstance();
MyMessageBox mmsg2 = MyMessageBox.GetInstance();
OtherObject.ShowAnother(mmsg1);
mmsg2.Show("asd","asd");

یعنی الان چند ارجاع به یک نمونه از شیئ MyMessageBox داریم. اما در حالت static نه تنها یک نمونه داریم، بلکه فقط یک ارجاع به اون شیئ میتونه وجود داشته باشه، نه بیشتر. البته میشد از سینگلتن هم استفاده کنیم و متد GetInstance رو پیاده سازی نکنیم تا نشه ارجاعهای مختلفی به اون نمونه داشت. اما شاید دیگه نشه به عنوان یک Singleton Pattern روی این کلاس حساب باز کرد.

کلاس static که همان کلاس باقی مانده و از شیئ object هم به ارث رسیده، فقط یک تغییر در نحوه دسترسی (modifier) به این کلاس اضافه شده که static باشد، یعنی تنها یک نمونه و تنها یک ارجاع.

مثلا کلاس MessageBox ای که در دات نت هست رو نگاه کنید، این کلاس static نیست اما متد سازنده این کلاس private است یعنی نمیشه ازش نمونه ای ایجاد کرد و یا ارجاع دیگه ای ازش داشت، همچنین متدهای Show این کلاس (که Overload شده اند)، بصورت static هستند، در واقع این کلاس رفتاری شبیه به یک کلاس static رو داره اما چرا بصورت static تعریف نشده؟ من هم نمیدونم! شاید بخاطر سازگاری با دات نت 1 ...؟!؟

کلاسهای زیر، کلاسهای static در کتابخانه کلاس دات نت هستند که در فضای نام System.Net قرار دارند.


System.Net.Dns
System.Net.WebRequestMethods.File
System.Net.WebRequestMethods.Ftp
System.Net.WebRequestMethods.Http

اَرژنگ
جمعه 02 شهریور 1386, 02:02 صبح
مثلا کلاس MessageBox ای که در دات نت هست رو نگاه کنید، این کلاس static نیست اما متد سازنده این کلاس private است یعنی نمیشه ازش نمونه ای ایجاد کرد و یا ارجاع دیگه ای ازش داشت، همچنین متدهای Show این کلاس (که Overload شده اند)، بصورت static هستند، در واقع این کلاس رفتاری شبیه به یک کلاس static رو داره اما چرا بصورت static تعریف نشده؟ من هم نمیدونم! شاید بخاطر سازگاری با دات نت 1 ...؟!؟


به نکته جالی اشاره کردید.
این روش یک طریق دیگر استفاده از سینگلتن است.
تا جایی که من متوجه شدم، استفاده از یک کلاس استاتیک برایه یک مساج باکس روشه خوبی نیست.
در این مقاله بیشتر توضیح داده شده:

(http://msdn.microsoft.com/msdnmag/issues/02/11/CuttingEdge/)http://msdn.microsoft.com/msdnmag/issues/02/11/CuttingEdge/
The original Windows Forms MessageBox is a singleton object, with a single instance of the class to service all requests. The Show method is declared static and you don't need to explicitly instantiate the MessageBox object in order to show a popup.
(http://msdn.microsoft.com/msdnmag/issues/02/11/CuttingEdge/)

استفاده از یک کلاس استاتیک محدودیتهایه بوجود میاره که استفاده از سینگلتن نداره.
توضیحاهت بیشتر در این لینک:

Static Classes and Static Class Members (C# Programming Guide)
http://msdn2.microsoft.com/en-US/library/79b3xss3(VS.80).aspx


دلایل استفاده از یک کلاس استاتیک :

C# Whidbey Featurette #3: Static classes
http://blogs.msdn.com/ericgu/archive/2004/04/13/112274.aspx

PC2st
جمعه 02 شهریور 1386, 11:18 صبح
این روش یک طریق دیگر استفاده از سینگلتن است.
نکته جالبی بود :متفکر:



تا جایی که من متوجه شدم، استفاده از یک کلاس استاتیک برایه یک مساج باکس روشه خوبی نیست.
شاید اینطور باشه...



استفاده از یک کلاس استاتیک محدودیتهایه بوجود میاره که استفاده از سینگلتن نداره.
این حرف شما درسته،...
و این محدودیت شاید روزی لازم بشه.

PC2st
جمعه 02 شهریور 1386, 14:52 عصر
این جمله رو یکبار دیگه با دقت خوندم:

Search The original Windows Forms MessageBox is a singleton object, with a single instance of the class to service all requests. The Show method is declared static and you don't need to explicitly instantiate the MessageBox object in order to show a popup.
گفته که MessageBox یک شیئ یگانه (Singleton Object) است،

و منظورش این نبوده که MessageBox از Singleton Design Pattern استفاده کرده؟

یعنی MessageBox به روش Singleton Design Pattern طراحی نشده!

اَرژنگ
شنبه 03 شهریور 1386, 06:11 صبح
این جمله رو یکبار دیگه با دقت خوندم:

نقل قول:
Search The original Windows Forms MessageBox is a singleton object, with a single instance of the class to service all requests. The Show method is declared static and you don't need to explicitly instantiate the MessageBox object in order to show a popup.
گفته که MessageBox یک شیئ یگانه (Singleton Object) است،

http://en.wikipedia.org/wiki/Singleton_pattern
In (http://en.wikipedia.org/wiki/Singleton_pattern)software engineering (http://en.wikipedia.org/wiki/Software_engineering), the singleton pattern is a (http://en.wikipedia.org/wiki/Singleton_pattern)design pattern (http://en.wikipedia.org/wiki/Design_pattern_%28computer_science%29) that is used to restrict instantiation of a class to one (http://en.wikipedia.org/wiki/Singleton_pattern)object (http://en.wikipedia.org/wiki/Object-oriented_programming).
(http://en.wikipedia.org/wiki/Singleton_pattern)

در دات نت ۱.۰،۱.۱،۲.۰ تنها روش داشتن یک شئی یگانه، فقط با پیاده سازی سینگلتن پترن ممکن بود.




و منظورش این نبوده که MessageBox از Singleton Design Pattern استفاده کرده؟

یعنی MessageBox به روش Singleton Design Pattern طراحی نشده!
دلایلی که بر رسی کردید این نتیجه را نمیدهند. با چه روشه دیگری قبل از دات نت ۳.۰ ممکن است که بتوانیم یک شئی یگانه داشته باشیم بدونه استفاده از پترن سینگلتن؟

PC2st
شنبه 03 شهریور 1386, 16:57 عصر
دلایلی که بر رسی کردید این نتیجه را نمیدهند. با چه روشه دیگری قبل از دات نت ۳.۰ ممکن است که بتوانیم یک شئی یگانه داشته باشیم بدونه استفاده از پترن سینگلتن؟
کلاس MessageBox دارای اعضای static بوده و سازنده کلاس بصورت private است، در این حالت شبیه کلاس static عمل میکند.


حالا تعریف زیر که در MSDN و کتاب Introduction to Design Patterns in C# هست...


The intent of the Singleton pattern as defined in Design Patterns is to "ensure a class has only one instance, and provide a global point of access to it".

منظور از تامین کردن یک Global Point برای دسترسی به آن، چی میتونه باشه؟

(+) در لینکی که داده بودید (از سایت wikipedia)، اگر به نحوه ی تعریف کلاسها دقت کنید، همه کلاسهایی که از Singleton Design Pattern استفاده کرده اند، دارای متدی هستند (مثلا بنام GetInstance) که توسط آن متد میشه به یگانه شیئ دسترسی داشت (Global Point)

(+) همچنین اگر کدهای داخل MessageBox رو با Reflector مرور کنیم، میبینیم که تمام اعضای آن بصورت static هستند. در حالیکه در الگوی طراحی Singleton، اعضا نباید بصورت static باشند تا هر وقت که لازم بود بتوان الگوی طراحی Singleton را از بین برد و بصورت یک کلاس عادی از آن استفاده کرد.

اَرژنگ
یک شنبه 04 شهریور 1386, 04:52 صبح
کلاس MessageBox دارای اعضای static بوده و سازنده کلاس بصورت private است، در این حالت شبیه کلاس static عمل میکند.




ولی یک کلاس استاتیک نیست.
و سینگلتن پترن را پیاده کرده.
با اضافه شدنه کلاسهایه استاتیک نهوه پیاده کردن سینگلتن پترن در سی شارپ عوض شده ، یک کلاس استاتیک بطور اتوماتیک هدفهایه سینگلتن پترن را بر آورده میکنه. در همان لینک ویکی پدیا به این موضوع اشاره کرده.



حالا تعریف زیر که در MSDN و کتاب Introduction to Design Patterns in C# هست...
[code]
The intent of the Singleton pattern as defined in Design Patterns is to "ensure a class has only one instance, and provide a global point of access to it".

منظور از تامین کردن یک Global Point برای دسترسی به آن، چی میتونه باشه؟


یک Global Point برای دسترسی به آن، MessageBox.Show است.
فقط قابلیت داشتن دسترسی به کلاس سینگلتن (S) در یکجا است. مثلا به همین دلیل فقط در کلاسی که پیاده‌اش کرده(P۱) میشه به S دسترسی داشت، و از هر جایه دیگر باید با همان کلاس (P۱) کار کرد. اگر یک کلاس دیگر بخواد که با کلاس S کار کند فقط از طریق کلاس P۱ میتواند، و یک کلاس P۲ نباید دوباره با کلاس S ارتباط مستقیم داشته باشه (اگر هدف داشتن S فقط یکبار است).
a Global Point میشه یک کلاس هم باشه. همانطوری که میشه کلاسهایی internal باشند یک کلاس دیگر که public هستش میتواند به کلاس private دسترسی داشته باشه.
و این یک نحوه دیگر پیاده کردن Singletonاست (منتها وقتی که از خارج دات نت اسمبلی که این کلاسها را دارد)


(+) در لینکی که داده بودید (از سایت wikipedia)، اگر به نحوه ی تعریف کلاسها دقت کنید، همه کلاسهایی که از Singleton Design Pattern استفاده کرده اند، دارای متدی هستند (مثلا بنام GetInstance) که توسط آن متد میشه به یگانه شیئ دسترسی داشت (Global Point)


اگر به تعریفی که از کتاب C# Design Patterns دادید نگاه کنید این محدودیت را جزو پترن تعریف نکرده.
میگه a Global Access Point و نگفته که این Global Access Point باید حتما یک پروسیجر باشه.
کتابها همیشه از ساده ترین مثلاها استفاده میکنند که اصل مطلب را برسانند، از خودتان بپرسید که تا چه حدی میشه یک مثال را عوض کرد ولی هنوز به موضوع مروبوط ماند. الگوهایه طراهی بیشتر یک طرزه تفکر هستند تا یک الگریتم که باید نقطه به نقطه پیاده بشند.
مثالها را برایه شروع و امتحان تصور کنید نه به عنوان تعریف.




(+) همچنین اگر کدهای داخل MessageBox رو با Reflector مرور کنیم، میبینیم که تمام اعضای آن بصورت static هستند. در حالیکه در الگوی طراحی Singleton، اعضا نباید بصورت static باشند تا هر وقت که لازم بود بتوان الگوی طراحی Singleton را از بین برد و بصورت یک کلاس عادی از آن استفاده کرد.

۱_اگر با تمام اعضا منظورتان ShowMessage است پس اعضایه داخلی (private) کجا هستند؟
۲_اینکه باید کلاسی که سینگلتن پترن را پیاده میکنه همان کلاسی باشه که فقط یکبار ازش استفاده بشه جزوه تعریف سینگلتن پترن نیست.
۳_اینکه بتوان الگوی طراحی singleton را از بین برد و بصورت یک کلاس عادی از آن استفاده کرد نکته جالبی است ولی، جایی این شرط را جزوه سینگلتن پترن تعریف نکردند.
۴_با نگاه کردن در رفلکتور، به نظر میاد که اصلا دایالوگ باکسی وجود نداره، و این بیشتر مانند Wrapper Design Pattern هست تا سینگلتن ولی خصوصیت صدا زدن وینودز مساج باکس این را دارد که از جایه دیگر نمیشه دوباره کالش کرد. یعنی در برنامه هایه یک تردی همیشه فقط یک مساج باکس وجود داره و فقط به وسیله میشه بهش دسترسی داشت. یعنی این هم خصوصیات Singleton Design Pattern را بر آورده میکند و هم Wrapper Design Patternرا.
۵_در اصله این مطلب که درست کردن یک مساج باکس سفارشی است و من یک لینک به یک مقاله برایه اینکار فرستادم استفاده از Singleton Pettern را توصیه کرده و میشه که الگوی طراحی singleton را از بین برد و بصورت یک کلاس عادی از آن استفاده کرد

۶_استفاده از یک کلاس استاتیک برایه اینکار محدویتهایه بوجود میاره که پیاده کردن سینگلتن بوجود نمیاره. اول برنامه نویسی باید به فکر داشتن انعطاف پزیری بود تا بوجود آودرن محدودیت و اشاره‌ای که به داشتن محدویتها بعضا لازم است در این مورد صدق نمیکنه.

PC2st
یک شنبه 04 شهریور 1386, 17:36 عصر
ولی یک کلاس استاتیک نیست.
و سینگلتن پترن را پیاده کرده.
کلاس استاتیک نیست ولی شبیه به اون عمل میکنه.
به نظرم سینگلتن پترن هم نیست، مگر اینکه جمله زیر صحت داشته باشه! :

با اضافه شدنه کلاسهایه استاتیک نهوه پیاده کردن سینگلتن پترن در سی شارپ عوض شده ، یک کلاس استاتیک بطور اتوماتیک هدفهایه سینگلتن پترن را بر آورده میکنه. در همان لینک ویکی پدیا به این موضوع اشاره کرده.




یک Global Point برای دسترسی به آن، MessageBox.Show است.
متد Show یک Global Point به حساب نمیآد بلکه یک متد static برای اجرای عملیات حساب میشه.
تمام متدهای Show که Overload شدند، همشون استاتیک هستند و همه این متدها در داخل خود از متد private static ای بنام ShowCore استفاده کردند و در واقع همه چیز static است بجز متد سازنده که private است.

در واقع یکی از متدهای Show به شکل زیر پیاده سازی شده:


public static DialogResult Show(string text, string caption)
{
return ShowCore(null, text, caption, MessageBoxButtons.OK, MessageBoxIcon.None, MessageBoxDefaultButton.Button1, 0, false);
}


و متد ShowCore هم استاتیک است، یعنی:


private static DialogResult ShowCore(IWin32Window owner, string text, string caption, MessageBoxButtons buttons, MessageBoxIcon icon, MessageBoxDefaultButton defaultButton, MessageBoxOptions options, bool showHelp)
{
//...
}



فقط قابلیت داشتن دسترسی به کلاس سینگلتن (S) در یکجا است.
برخلاف تعریف سینگلتن پترن...
در سینگلتن پترن، قابلیت دسترسی داشتن به کلاس سینگلتن (S) از همه جا باید امکان پذیر باشه، یعنی مثلا از طریق 8 تا شیئ بشه به یک کلاس سینگلتن (S) دسترسی داشت اما، همه ی این 8 تا شیئ به یک نمونه (Singleton Object) اشاره میکنند.
اما در کلاس استاتیک نمیشه مثلا 8 تا شیئ داشت که به کلاس استاتیک اشاره کنند بلکه فقط یک شیئ میتونه به نمونه دسترسی داشته باشه و اون شیئ، خود کلاس static است. یعنی کلاس static چیزی بصورت Global Point نداره.



اگر به تعریفی که از کتاب C# Design Patterns دادید نگاه کنید این محدودیت را جزو پترن تعریف نکرده.
میگه a Global Access Point و نگفته که این Global Access Point باید حتما یک پروسیجر باشه.
منم همچنین حرفی رو نزدم. نگفتم که حتما باید متد باشه، مثلا Global Point میتونه یک private FIELD باشه و البته readonly و static.
ولی متدی مثل Show، یک Global Point نمیتونه باشه، چون به نمونه ای از کلاس اشاره نمیکنه (فقط یک سری اعمال رو انجام میده).


1. اعضای داخلی private همه آنها هم استاتیک هستند، چون در متدی مثل Show نمیشه از اعضای غیر استاتیک استفاده کرد چون متد SHow یک متد static است.

2. بله، جزء تعریف نیست.

3. بله، جایی رو برای این شرط تعیین نکردند.

4. چون فقط یک شیئ وجود داره، نمیشه گفت که Singleton Pattern رو پیاده سازی کرده، کلاس static هم فقط اجازه دسترسی به یک شیئ رو امکان پذیر میسازه (یا کلاسی مثل MessageBox).

5. درسته، خوبه که اینطور باشه.

6. بله، موافقم. محدودیتهایی کلاس استاتیک داره، مثلا همین اینکه اگر کلاسی بصورت استاتیک ایجاد بشه، دیگه براحتی نمیشه اون رو به غیر استاتیک تبدیل کرد.

اَرژنگ
دوشنبه 05 شهریور 1386, 03:53 صبح
کلاس استاتیک نیست ولی شبیه به اون عمل میکنه.
به نظرم سینگلتن پترن هم نیست، مگر اینکه جمله زیر صحت داشته باشه! :


راحت میشه صحت داشتن و یا نداشتن این جمله را پیدا کرد: اگر تعریف الگویه سینگلتن را برآورده میکند صحت دارد اگر که نه خیر!
من نمیبینم که کدام نیازهایه سینگلتن پترن را براآورده نمیهنه، اگر کسی بتواند کمک کند که چه تضادی با سینگلتن پترن داره ممنون میشم.

در ضمن حتما هم قرار نیست که با کلاس استاتیک پیاده بشه، کلاس استاتیک یک روش دیگر به پیاده کردن سینگلتن در سی شارپ اضافه میکنه و خیلی راه هایه دیگری هم هستند که سینگلتن را پیاده میکنند.



متد Show یک Global Point به حساب نمیآد بلکه یک متد static برای اجرای عملیات حساب میشه.


کی این یکی کد را ترجیح میده



MessageBox msgBox = MessageBox.GetInstance();
msgBox.ShowMessage( " Blah Blah ");


به این یکی کد؟



MessageBox.ShowMessqage( "Blah Blah" );





برخلاف تعریف سینگلتن پترن...
در سینگلتن پترن، قابلیت دسترسی داشتن به کلاس سینگلتن (S) از همه جا باید امکان پذیر باشه، یعنی مثلا از طریق 8 تا شیئ بشه به یک کلاس سینگلتن (S) دسترسی داشت اما، همه ی این 8 تا شیئ به یک نمونه (Singleton Object) اشاره میکنند.
اما در کلاس استاتیک نمیشه مثلا 8 تا شیئ داشت که به کلاس استاتیک اشاره کنند بلکه فقط یک شیئ میتونه به نمونه دسترسی داشته باشه و اون شیئ، خود کلاس static است. یعنی کلاس static چیزی بصورت Global Point نداره.


کلاس static خودش یک Global Point است.



منم همچنین حرفی رو نزدم. نگفتم که حتما باید متد باشه، مثلا Global Point میتونه یک private FIELD باشه و البته readonly و static.
ولی متدی مثل Show، یک Global Point نمیتونه باشه، چون به نمونه ای از کلاس اشاره نمیکنه (فقط یک سری اعمال رو انجام میده).

لازم نیست که اشاره کنه، ترجمه a Global Access Point
یعنی اینکه که از همه جا بشه بهش دسترسی داسی.
معنی این دسترسی حتما اینکه باید بهش اشاره کرد نیست.
مثل یک در که با یک دگمه میشه باز و بستش، حالا کسی که به این دگمه دسترسی داره به در هم دسترسی داره و نیازی نداره که با خود در تماس داشته باشه.




1. اعضای داخلی private همه آنها هم استاتیک هستند، چون در متدی مثل Show نمیشه از اعضای غیر استاتیک استفاده کرد چون متد SHow یک متد static است.

میشه یک شئی ایجاد کرد و به آن دسترسی داشت، روش ساده نوشتن یک مساج باکس در خود دات نت هم همین طوری است.




4. چون فقط یک شیئ وجود داره، نمیشه گفت که Singleton Pattern رو پیاده سازی کرده، کلاس static هم فقط اجازه دسترسی به یک شیئ رو امکان پذیر میسازه (یا کلاسی مثل MessageBox).


سینگلتن اجازه دسترسی به یک شیئ نیست! فقط اجازه دسترسی به یک شیئ است.
لازم نیست که معنی دسترسی (Access) حتما داشتن یک اشاره به شئی باشه، بلکه داشتن کنترل بر کارهایی که شئی میواند انجام بدهد هم حساب میش (؟ شما چی فکر میکنید؟ چونکه من این مطلب را اینطوری درک کردم دلیل نمیشه ، دنبال یک مقاله میگردم که این نقطه را روشن کند.)
کلاس استاتیک و مساج باکس فقط اجازه دسترسی به یک شیئ را میدند. به همین دلیل من فکر میکنم که هر دو شان شرایط سینگلتن را برآوردند . حالا ممکنه که با سینگلتن طراحی نشده باشند، ولی خصوصایت یک الگویه (الگو و نه یک شئی سینگلتن) را بر آوردند.

اَرژنگ
دوشنبه 05 شهریور 1386, 05:13 صبح
با عرض تشکر از نظراتتان، شما به نکاتی اشاره کردید که حالا من را شک انداخته و دارم دنبال معنی عمیقتر برایه این مطالب میگردم.
من یک مثال ساده ضمیمه کردم که کد اصلیش این است:



private static MessageBox instance;
private MessageBox()
{
InitializeComponent();
}
public static DialogResult ShowMessage(string Message)
{
if (instance == null)
{
instance = new MessageBox();
instance.label1.Text = Message;
}
return instance.ShowDialog();
}
}


به نظر من این کد شرایط سینگلتن را ارضا میکند، من خوشحال میشم که دلایلی که این کد الگویه سینگلتن را میشکند را هم ببینم. انشاالله بعد از اینکه این بحث سینگلتن به نتیجه رسید بریم سراغه بقیه الگوها :)

PC2st
دوشنبه 05 شهریور 1386, 17:35 عصر
در ضمن حتما هم قرار نیست که با کلاس استاتیک پیاده بشه، کلاس استاتیک یک روش دیگر به پیاده کردن سینگلتن در سی شارپ اضافه میکنه و خیلی راه هایه دیگری هم هستند که سینگلتن را پیاده میکنند.
از این نظر مطمئن نیستم، چون به قول خودتون، شراط الگوی طراحی 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 مرداد) نمیتونم به این فروم بیام و به اینترنت وصل بشم، اما بعد از گذشت یک هفته، دوباره به سایت میام و پاسخ های شما رو نگاه میکنم.
امیدوارم که اگر پاسخی داشتید یا مطلبی رو لازم دونستید رو بنویسید تا من یک هفته بعد بیام و بحث رو از سر بگیریم تا با رد و بدل کردن صحبت ها، به نتایج لازم برسیم.

امیدوارم که اگر لازم بود، بحث ادامه پیدا کنه.

اَرژنگ
سه شنبه 06 شهریور 1386, 04:11 صبح
یک کم دیگه منظورم رو بهتر برسونم که منظور از global point of access to it حتما باید نمونه شیئ باشه. چون مثلا وقتی که از یک کلاس static استفاده میکنیم، فقط و فقط کلاس static میتونه به نمونه خودش دسترسی داشته باشه، پس برای دسترسی به نمونه شیئ یک کلاس استاتیک، حتما باید از نام خود کلاس static استفاده کنیم، چون به هیچ وجه به نمونه (One Instance) دسترسی نداریم، بلکه کلاس static به آن دسترسی داره.
اما وقتی که از الگوی طراحی singleton استفاده میشه، توسط این الگو، نمونه شیئ (منظورم همان one instance) رو بعنوان یک فیلد یا مقدار برگشتی یک متد، مورد دسترسی دیگر کلاسها قرار میده و کلاس مثلا همون ccc میتونه بهش دسترسی داشته باشه، درصورتی که در کلاس static، فقط کلاس استاتیک میتونه دسترسی داشته باشه.

قسمتی را که سبز کردم و زیرش را خط کشیدم، همه چی را کاملا روشن میکند.
متشکر از زحماتتان.