PDA

View Full Version : سوال: چرا از الگوی سینگلتون استفاده میکنیم وقتی کلاس استاتیک وجود دارد



alireza_tavakol
دوشنبه 23 شهریور 1388, 05:47 صبح
هدف از استفاده کلاس با الگوی سینگلتون : میخواهیم تضمین کنیم که از یک کلاس تنها بتوان یک آبجکت ایجاد کرد و همه ی درخواستها نیز تنها به همان یک آبجکت هدایت شوند و نیز بتوان یک دسترسی عمومی به آن داشت.

سوال من : وقتی کلاسی از نوع استاتیک تعریف شود هدف بالا نیز حاصل می گردد. پس آیا نیازی هست که از الگوی سینگلتون استفاده شود؟

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

SMRAH1
سه شنبه 24 شهریور 1388, 05:56 صبح
سلام

دو تا نکته به ذهنم رسید:
1) در کلاس استاتیک وراثت نداریم ولی در کلاس معمولی (حتی اگر الگوی سنگلتون رو برایش پیاده کنیم) می تونیم از وراثت استفاده کنیم(منظورم اینکه کلاس سینگلتون پیاده سازی شده می تونه مورث یک کلاس دیگه باشه).
2) شما در کلاس باید یک تابع سازنده داشته باشید که وظیفه مقدار دهی اولیه رو بر عهده داره.اگر بخواهید این رو در کلاس استاتیک انجام بدید،باید تابعی ،مثلا با نام Load ،که وظیفه مقدار دهی اولیه به متغیر های و ... کلاس رو بر عهده داره،پیاده سازی کنید.حالا با این توضیف یک سئوال هنوز وجود داره؟ «چطور می تونید از وجود فقط یک نوع از این کلاس اطمینان حاصل کنید؟» به عبارت دیگه در الگوی سینگلتون،شما تابعی دارید ،مثلا GetInstance، که تنها نمونه کلاس رو بر می گردونه (اگر این نمونه وجود نداشته باشه،اون رو ساخته و بر می گردونه ولی اگر اون رو قبلا ساخته باشه،همون رو بر می گردونه).اما شما در کلاس استاتیک چطور می خواهید این را (به راحتی)پیاده سازی کنید.چه تضمینی وجود دارد که تابع Load را دوباره فراخوانی نکنید (تاکید می کنم که پیاده سازی این حالت در کلاس استاتیک امکان پذیر است،ولی کمی پیچیده می شود).

موفق باشید

JaguarXF
سه شنبه 24 شهریور 1388, 07:52 صبح
برای اینکه وقتی استتیک باشه فقط یک اینستنس از اون میتونه موجود باشه.

سینگلتون میگه : هر کاربر : یک اینستنس
استتیک میگه: کلهم اجمعین : یک اینستنس

برنامه تک کاربره که نمیخواید بنویسید . ( شایدم میخواید!)

prankster
سه شنبه 24 شهریور 1388, 08:44 صبح
1- از كلاس static نمي توان instance ساخت، كلاس فقط در حافظه بارگزاري مي شود و به اجزاي static آن مي توان دسترسي داشت!
2- كلاس static مفهومي است كه تنها در Net. وجود دارد و پلتفرم هاي شيء گراي ديگر از آن پشتيباني نمي كنند
3- الگو هاي متفاوتي براي پياده سازي singelton وجود دارد كه هيچ كدام شامل static class ها نمي شوند!

alireza_tavakol
پنج شنبه 26 شهریور 1388, 10:03 صبح
1) در کلاس استاتیک وراثت نداریم ولی در کلاس معمولی (حتی اگر الگوی سنگلتون رو برایش پیاده کنیم) می تونیم از وراثت استفاده کنیم(منظورم اینکه کلاس سینگلتون پیاده سازی شده می تونه مورث یک کلاس دیگه باشه).

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


2) شما در کلاس باید یک تابع سازنده داشته باشید که وظیفه مقدار دهی اولیه رو بر عهده داره.اگر بخواهید این رو در کلاس استاتیک انجام بدید،باید تابعی ،مثلا با نام Load ،که وظیفه مقدار دهی اولیه به متغیر های و ... کلاس رو بر عهده داره،پیاده سازی کنید.حالا با این توضیف یک سئوال هنوز وجود داره؟ «چطور می تونید از وجود فقط یک نوع از این کلاس اطمینان حاصل کنید؟» به عبارت دیگه در الگوی سینگلتون،شما تابعی دارید ،مثلا GetInstance، که تنها نمونه کلاس رو بر می گردونه (اگر این نمونه وجود نداشته باشه،اون رو ساخته و بر می گردونه ولی اگر اون رو قبلا ساخته باشه،همون رو بر می گردونه).اما شما در کلاس استاتیک چطور می خواهید این را (به راحتی)پیاده سازی کنید.چه تضمینی وجود دارد که تابع Load را دوباره فراخوانی نکنید (تاکید می کنم که پیاده سازی این حالت در کلاس استاتیک امکان پذیر است،ولی کمی پیچیده می شود).

به نظر من این پاسخ شما نوعی از فرافکنی است چون خود شما استحضار دارید که پیاده سازی متدی که فقط قرار باشد یک بار اجرا تاثیر گذار داشته باشد به سادگی نوشین جرعه ای آب می باشد

پس نمی توان با این دو موردی که شما فرمودید استدلالی بر وجود الگوی سینگلتون داشت

alireza_tavakol
پنج شنبه 26 شهریور 1388, 10:05 صبح
برای اینکه وقتی استتیک باشه فقط یک اینستنس از اون میتونه موجود باشه.

سینگلتون میگه : هر کاربر : یک اینستنس
استتیک میگه: کلهم اجمعین : یک اینستنس

برنامه تک کاربره که نمیخواید بنویسید . ( شایدم میخواید!)

متاسفانه من منظور شما رو از برنامه تک کاربره بد فهمیدم ، شاید اصلا" نفهمیدم:افسرده:

آیا منظور شما اینکه ، وقتی هم زمان چند بار فایل اجرایی برنامه من اجرا شده برنامه رو چند کاربره حساب کنیم و وقتی فقط یک بار اجرا شده تک کاربره حساب کنیم ؟

اگه منظورتون این باشه ! باید به عرضتون برسونم که در شرایط بالا اگه کلاس از الگوی سینگلتون پیروی کنه و یا از نوع static تعریف شده باشه هیچ فرقی نخواهند کرد و برای هر فایل exe نسخه ای مجزا از کلاس ها در حافظه قرار خواهد گرفت.

alireza_tavakol
پنج شنبه 26 شهریور 1388, 10:08 صبح
2- كلاس static مفهومي است كه تنها در Net. وجود دارد و پلتفرم هاي شيء گراي ديگر از آن پشتيباني نمي كنند

:متعجب:
دوست عزیز لطفا" کمی دقیقتر بفرمایید کدام پلتفرم شی گرا را می فرمایید
در جاوا و جاوا اسکیریپت کلاس ststic وجود دارد برای مثال کلاس math برای دسترسی به توابع معروف ریاضیات



3- الگو هاي متفاوتي براي پياده سازي singelton وجود دارد كه هيچ كدام شامل static class ها نمي شوند!
از کلام شما این گونه استنباط کردم که می توان الگوی سینگلتون را بدون استفاده از واژه static پیاده سازی کرد! اگر برداشت من صحیح است لطفا" با مثالی نشان دهید چگونه سینگلتون را بدون متغیر یا متد static پیاده سازی می نمایید:لبخندساده:

با تشکر/

صابر
پنج شنبه 26 شهریور 1388, 11:49 صبح
http://dotnetperls.com/singleton-static
به طور خلاصه:
1- می‌توان از singleton به عنوان پارامتر یک متد استفاده کرد.
2- می‌توان آن را به یک متد که یک interface به عنوان ورودی می‌پذیرد ارسال کرد.
3- کلاس‌های static دقیقاً مشخص نیست کی initialize‌ می‌شوند و معمولاً دقیقاً قبل از استفاده از آنها این اتفاق می‌افتد.
4- Constructorهای static کند هستند. (http://dotnetperls.com/static-constructor)
------------------------
این هم نمونه‌ای از مشکل استفاه از static:
http://dotnet.org.za/reyn/archive/2004/07/07/2606.aspx

SMRAH1
پنج شنبه 26 شهریور 1388, 11:58 صبح
سلام

به نکات بالا،این رو هم اضافه کنید (برنامه به نظر کاملا گویا است):

namespace staticSingelton
{
class Program
{
static void Main(string[] args)
{
StaBase.StaBase1 = 1;
StaBase.StaBase2 = 2;
Sta1.Sta11 = 11;
Sta2.Sta21 = 21;

Write("Default Value");

Console.WriteLine("change Sta1.StaBase1 to 111");
Sta1.StaBase1 = 111;
Console.WriteLine("Effect in Sta2.StaBase1 !!!!");
Console.WriteLine("Sta2.StaBase1 = {0}", Sta2.StaBase1);
Console.WriteLine();

Write("Current Value");
}

private static void Write(string s)
{
Console.WriteLine(" ---- {0} ----", s);
Console.WriteLine("StaBase.StaBase1 = {0}", StaBase.StaBase1);
Console.WriteLine("StaBase.StaBase2 = {0}", StaBase.StaBase2);
Console.WriteLine("Sta1.Sta11 = {0}", Sta1.Sta11);
Console.WriteLine("Sta2.Sta21 = {0}", Sta2.Sta21);
Console.WriteLine();
}

/**********************************************/
public class StaBase
{
public static int StaBase1 = 0;
public static int StaBase2 = 0;
}

public class Sta1 : StaBase
{
public static int Sta11 = 0;
}

public class Sta2 : StaBase
{
public static int Sta21 = 0;
}
}
}

در ضمن من تاکید کردم که شبیه سازی GetInstance در کلاس استاتیک ،غیر ممکن نیست،با این حال باید تاکید کنم که این پیاده سازی «به سارگی استفاده از الگوی سینگلتون» نیست!
در واقع می خواهم این نکته را یاد آور شوم که قابلیت هایی که در اختیار یک برنامه نویس است (مثل قابلیت های زبان یا الگو ها یا توابع آماده و ..) باعث افزایش و دقت کد نویسی خواهد شد (توسعه و پیاده سازی).مثلا فرض کنید که کلا از کلاس ها در برنامه نویسی استفاده نکنیم!آیا با این حساب نمی توان برنامه نویسی کرد؟.قطعا می توان برنامه نوشت ولی با استفاده از کلاس ها ،راحت تر و پایدارتر می توان نوشت.

موفق باشید

alireza_tavakol
پنج شنبه 26 شهریور 1388, 11:58 صبح
با تشکر از دوستان پاسخ دهند:لبخندساده:

یکی از دوستان من یک نظریه جالبی داشت مبنی بر اینکه:

وقتی ما درباره الگوی سینگلتون صحبت میکنیم ، در واقع داریم مفهومی عمومی را مورد بررسی قرار می دهیم واصلا" روش پیاده سازی مهم نیست

منظورش این بود که مثلا" ممکنه یکی مفهوم سینگلتون را توسط کلاسی پیاده سازی کنه که سازنده ای private داشته باشه و یک عضو از جنس همان کلاس را به صورت static تعریف کنه و متدی با خروجی از نوع نمونه همان کلاس داشته باشه

و شخص دیگری مفهوم سینگلتون را توسط یک کلاس کاملا" static پیاده سازی کنه یا مثلا" یک کلاسی که همه اعضاش static باشه و ...

آیا این تعریف در رابطه با الگوی:متفکر: سینگلتون درسته؟

alireza_tavakol
پنج شنبه 26 شهریور 1388, 12:50 عصر
سلام . . . (http://www.barnamenevis.org/forum/showpost.php?p=807740&postcount=9)
برای جلوگیری از طولانی شدن پست متن نقل قول رو حذف کردم برای مراجه از لینک استفاده کنید



با تشکر از شما دوست گرامی

اگه منظور شما را از مطرح کردن این مثال درست متوجه شده باشم ، می خواستین نشون بدین اگه از روش static کردن اعضا ، وراث را پیاده سازی کنیم side effect داریم ولی اگه از روش الگوی سینگلتون کلاس ها را طراحی کنیم تاثیر جانبی در متغییر های base را نداریم!

من مثال شما را با روش الگوی سینگلتون باز نویسی کردم ولی همچنان side effect پای برجاست! اگه جایی را اشتباه کردم بفرمایید


namespace staticSingelton
{
class Program
{
static void Main(string[] args)
{
StaBase.GetInstance().StaBase1 = 1;
StaBase.GetInstance().StaBase2 = 2;
Sta1.Getinstance().Sta11 = 11;
Sta2.Getinstance().Sta21 = 21;

Write("Default Value");

Console.WriteLine("change Sta1.StaBase1 to 111");
Sta1.GetInstance().StaBase1 = 111;
Console.WriteLine("Effect in Sta2.StaBase1 !!!!");
Console.WriteLine("Sta2.StaBase1 = {0}", Sta2.GetInstance().StaBase1);
Console.WriteLine();

Write("Current Value");
Console.ReadLine();
}

private static void Write(string s)
{
Console.WriteLine(" ---- {0} ----", s);
Console.WriteLine("StaBase.StaBase1 = {0}", StaBase.GetInstance().StaBase1);
Console.WriteLine("StaBase.StaBase2 = {0}", StaBase.GetInstance().StaBase2);
Console.WriteLine("Sta1.Sta11 = {0}", Sta1.Getinstance().Sta11);
Console.WriteLine("Sta2.Sta21 = {0}", Sta2.Getinstance().Sta21);
Console.WriteLine();
}

/**********************************************/
public class StaBase
{
//private StaBase()
//{}
private static StaBase instance;
public static StaBase GetInstance()
{
if (instance == null)
instance = new StaBase();
return instance;
}
public int StaBase1 = 0;
public int StaBase2 = 0;
}

public class Sta1 : StaBase
{
private Sta1()
{}
private static Sta1 instance;
public static Sta1 Getinstance()
{
if (instance == null)
instance = new Sta1();
return instance;
}
public int Sta11 = 0;
}

public class Sta2 : StaBase
{
private Sta2()
{}
private static Sta2 instance;
public static Sta2 Getinstance()
{
if (instance == null)
instance = new Sta2();
return instance;
}
public int Sta21 = 0;
}
}
}
با تشکر /:لبخندساده:

SMRAH1
پنج شنبه 26 شهریور 1388, 14:43 عصر
سلام

در کد بالا نکته جالبی بود.بهتر اجرای کد زیر را ببینید:

namespace staticSingelton
{
class Program
{
static void Main(string[] args)
{
StaBase.GetInstance().StaBase1 = 1;
StaBase.GetInstance().StaBase2 = 2;
Sta1.Getinstance().Sta11 = 11;
Sta2.Getinstance().Sta21 = 21;

Write("Default Value");

Console.WriteLine("change Sta1.StaBase1 to 111");
Sta1.GetInstance().StaBase1 = 111;
Console.WriteLine("Effect in Sta2.StaBase1 !!!!");
Console.WriteLine("Sta2.StaBase1 = {0}", Sta2.GetInstance().StaBase1);
Console.WriteLine();

Write("Current Value");
Console.ReadKey();
}

private static void Write(string s)
{
Console.WriteLine(" ---- {0} ----", s);
Console.WriteLine("StaBase.StaBase1 = {0}", StaBase.GetInstance().StaBase1);
Console.WriteLine("StaBase.StaBase2 = {0}", StaBase.GetInstance().StaBase2);
Console.WriteLine("Sta1.StaBase1 = {0}", Sta1.GetInstance().StaBase1);
Console.WriteLine("Sta1.StaBase2 = {0}", Sta1.GetInstance().StaBase2);
Console.WriteLine("Sta2.StaBase1 = {0}", Sta2.GetInstance().StaBase1);
Console.WriteLine("Sta2.StaBase2 = {0}", Sta2.GetInstance().StaBase2);
Console.WriteLine("Sta1.Sta11 = {0}", Sta1.Getinstance().Sta11);
Console.WriteLine("Sta2.Sta21 = {0}", Sta2.Getinstance().Sta21);
Console.WriteLine();
}

/**********************************************/
public class StaBase
{
//private StaBase()
//{}
private static StaBase instance;
public static StaBase GetInstance()
{
Console.WriteLine("**** GetInstance from : StaBase");
if (instance == null)
instance = new StaBase();
return instance;
}
public int StaBase1 = 0;
public int StaBase2 = 0;
}

public class Sta1 : StaBase
{
private Sta1()
{ }
private static Sta1 instance;
public static Sta1 Getinstance()
{
Console.WriteLine("**** GetInstance from : Sta1");
if (instance == null)
instance = new Sta1();
return instance;
}
public int Sta11 = 0;
}

public class Sta2 : StaBase
{
private Sta2()
{ }
private static Sta2 instance;
public static Sta2 Getinstance()
{
Console.WriteLine("**** GetInstance from : Sta2");
if (instance == null)
instance = new Sta2();
return instance;
}
public int Sta21 = 0;
}
}
}

موفق باشید

alireza_tavakol
پنج شنبه 26 شهریور 1388, 22:06 عصر
در کد بالا نکته جالبی بود.بهتر اجرای کد زیر را ببینید:


با سلام

ببخشید اگه اذیت میکنم :خجالت: ولی به نظر بنده حقیر نه تنها هیچ نکته جالبی در کد ذکر شده وجود ندارد بلکه معتقد هستم کلاس static ساده تر و قابل فهم تر می باشد نسبت به کلاسی که از الگوی سینگلتون استفاده کرده.

لطفا کمی واضح تر بفرمایید کدام بخش از کد بالا باعث جلب توجه شما شده یا اینکه مثالی بزنید که فقط توسط الگوی سینگلتون قابل پیاده سازی باشد یا مثالی بزنید پیاده سازی آن توسط کلاس static بسیار دشوار باشد .

با تشکر/

اَرژنگ
جمعه 27 شهریور 1388, 04:36 صبح
با سلام

ببخشید اگه اذیت میکنم :خجالت: ولی به نظر بنده حقیر نه تنها هیچ نکته جالبی در کد ذکر شده وجود ندارد بلکه معتقد هستم کلاس static ساده تر و قابل فهم تر می باشد نسبت به کلاسی که از الگوی سینگلتون استفاده کرده.

لطفا کمی واضح تر بفرمایید کدام بخش از کد بالا باعث جلب توجه شما شده یا اینکه مثالی بزنید که فقط توسط الگوی سینگلتون قابل پیاده سازی باشد یا مثالی بزنید پیاده سازی آن توسط کلاس static بسیار دشوار باشد .

با تشکر/

در پست شماره ۸ جناب صابر دلیلهایه برتری پیاده کردن الگویه سینگلتن را به جایه استفاده کردن از کلاس استاتیک برایه اسفاده بری از خصوصیتهایی که سینگلتن پیاده میکند گفتند. جناب SMRAH1 هم انعتاف ناپزیریهایه استفاده کردن از کلاس استاتیک را نام بردند.

اگرچه در ظاهر کلاس استاتیک بعضی از خواص الگویه سینگلتن را مهیا میکند، ولی انعتاف ناپزیری که بوجود میاورد به استفاده اش نمیارزه.
اگر روشی ساده‌است دلیل بر استفاده شدن ازش نمیشه، برایه مثال در همین انجمن بارها دیده‌اید که برایه انتقال داده‌ها بین دو فرم (دو شیئ) کاربران بی‌تجربه استفاده از این دو روش را تجویز میکنند :
۱.استفاده از یک پروپرتی استاتیک در یک کلاس دیگر و
۲.پابلیک کردن ِعضوهایه یک فرم برایه استفاده در یک فرم دیگر.
هر دو راههایه بسیار ساده و بسیار اشتباهی هستند، اگرچه ساده نگهداشتن یک چیزی خوب است و مشکلاتی که بوجود میارند در به استفاده‌شان نمیارزند.
کلاس استاتیک هم محدودیتهایی دارد:
۱.چونکه از یک کلمه کلیدی زبان برایه کاری که بیشتر ازش استفاده میشه ، در شروع به نظر بیمشکل میاد ولی اگر خواستید چیزی را عوض کنید، به جز کلمه کلیدی مقدار مانور زیادی ندارید.
در ضمن یکی از بیشترین جاهایی که میشه این کمبود را دید وقتی است که به این سوال متکرری برمیخوریم:
من میخواهم در برنامه‌ام فقط یک فرم باشد.
حالا این را با کلاس استاتیک نمیشه سینگلتنش کرد، ولی الگویه سینگتن را میشه در فرم بازسازی کرد.

پس دلایل استفاده نکردن از کلمه کلیدی استاتیک و تبدیل یک کلاس به استاتیک برایه اینکه به حالت سینگلتن باهاش کار کرد را میشه در دو نقطه خلاصه کرد:
۱.انعتاف ناپزیری.
۲.محدویتهایه کاربردی.
شاید در حالتهایه بخصوصی اشکال نداشته باشد، ولی در کل نمیشه به شکل یکسان ازش استفاده کرد.استفاده کردن به شکل یکسان در برنامه‌نویسی از نون شب واجبتر است.

meysam_pro
جمعه 27 شهریور 1388, 11:48 صبح
جدای از بحث های بالا من یه سوالی مطرح میکنم و اون اینه که چرا باید از Staticها استفاده بکنیم؟
اگه Resharper یا CodeRush رو ، رو VS نصب کرده باشین، وقتی یک متد، فقط الگوریتمیک باشه(یه ورودی بگیره و یه خروجی بده) این افزونه ها پیشنهاد میکنن که متد رو static بکنیم.


به نظر من هر موقع کلمات static ، getSomething ، setSomething تو کلاس ها زیاد باشه ، اونقدر کد به سمت اسپاگتی شدن پیش میره.

اندر مزایای الگوی سینگلتون بگم که ، اگه آبجکت Facade رو به صورت سینگلتون تعریف کنید و تو Splash برای اولین بار Instance بگیرین ازش، میتونین تو Performance برنامه تون ، شاهد بهبود باشین.

JaguarXF
پنج شنبه 09 مهر 1388, 09:29 صبح
هدف از استفاده کلاس با الگوی سینگلتون : میخواهیم تضمین کنیم که از یک کلاس تنها بتوان یک آبجکت ایجاد کرد و همه ی درخواستها نیز تنها به همان یک آبجکت هدایت شوند و نیز بتوان یک دسترسی عمومی به آن داشت.

سوال من : وقتی کلاسی از نوع استاتیک تعریف شود هدف بالا نیز حاصل می گردد. پس آیا نیازی هست که از الگوی سینگلتون استفاده شود؟

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

وقتی برنامه چند نخی باشه ، هر نخ میتونه یک اینستنس رو بسازه که میتونه خطرناک باشه.
در یک پیاده سازی خوب ، از nested class باید استفاده کرد جهت حصول lazy instantiation

meysam_pro
شنبه 11 مهر 1388, 13:09 عصر
در یک پیاده سازی خوب ، از nested class باید استفاده کرد جهت حصول lazy instantiation
دلیل؟؟
تو طراحی شی گرا، باید مینیم Coupling داشته باشیم، حالا شما میگین Nested Class داشته باشیم؟