campaign-off40

الگوی طراحی سینگلتون (Singleton Design Pattern)



visibility  
mode_comment   ۶

الگوهای طراحی به منظور حل مشکلات متداول در شیوه برنامه نویسی شی گرا توسط برنامه نویسان باتجربه ایجاد شدند. این نوع مشکلات مستقل از زبان های برنامه نویسی هستند. یکی از این پرکاربردترین الگوهای طراحی، الگوی طراحی سینگلتون یا Singleton است. سینگلتون یک الگوی طراحی سازنده یا Creational است که به شما این اطمینان را می دهد که از یک کلاس تنها یک نمونه یا شی ساخته می شود.

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

الگوی طراحی سینگلتون چه مشکلاتی را برطرف می کند

الگوی Singleton در یک زمان دو مشکل را حل می کند و تنها اصل مسئولیت یا Single Responsibility را نقض می کند:

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

اما شاید برای شما جای سوال باشد که چرا کسی بخواهد این موضوع را مدیریت کند که تعداد نمونه های یک کلاس بیشتر از یک عدد نباشد؟ رایج ترین دلیل این امر کنترل دسترسی به برخی از منابع مشترک است. زیرا هر یک از این اشیای ساخته شده بخشی از منابع را به خود اختصاص می دهند. تصور کنید که شما یک شی از یک کلاس را ایجاد کرده اید، اما بعد از مدتی تصمیم به ایجاد یک شی جدید از آن کلاس می گیرید. بنابراین اگر از الگوی طراحی سینگلتون استفاده نکنید به جای استفاده از شی ای که قبلا ساخته اید، شی ای جدید می سازید که این کار از نظر مصرف منابع هزینه بر و غیر بهینه است. جالب است بدانید که ممکن است حتی کلاینت ها متوجه نشوند که در تمام مدت در حال استفاده از یک شی بوده اند.

اگر از الگوی طراحی سینگلتون استفاده نکنیم چه می شود؟

پیاده سازی الگوی طراحی سینگلتون

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

الگوی طراحی سینگلتون در برنامه نویسی

singleton design pattern الگوی طراحی سینگلتون

معمولا در در نرم افزارها وظیفه برقراری ارتباط با دیتابیس را بر عهده یک شی قرار می دهند. بنابراین برای اینکه مطمئن شویم نمونه ها و شی های دیگری برای انجام این کار از کلاس ایجاد نمی شوند، بهترین کار استفاده از الگوی طراحی Singleton است. با این روش برای هر بار برقراری ارتباط با دیتابیس نیاز به ساخت شی ای جدید نخواهیم داشت و تنها با ساخت یک شی از کلاس DBConnection، برای همیشه از آن استفاده خواهیم کرد.

بر این اساس تنها یکبار از کیورد new در کدهای خود استفاده خواهیم کرد و پس از آن فقط از تابع getInstance الگوی طراحی سینگلتون استفاده می کنیم. این تابع وظیفه دارد که دسترسی به تنها شی ای که از کلاس DBConnection ساخته شده است را برای ما فراهم کند. زیرا امکان وجود ساخت بیش از یک شی از روی این کلاس نه تنها ضرورتی ندارد و علاوه بر اینکه حافظه بیشتری مصرف می کند ممکن است منجر به بروز مشکل در نرم افزار ما نیز شود.

نحوه پیاده سازی الگوی طراحی سینگلتون

سینگلتون الگوی طراحی singleton

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

  1. اضافه کردن یک متغیر Static از نوع Private به کلاس مورد نظر به منظور ذخیره سازی نمونه Singleton در آن.
  2. نوشتن یک تابع Static از نوع Public برای دریافت نمونه ساخته شده Singleton (این تابع ورودی نخواهد داشت).
  3. پیاده سازی "مقدار دهی اولیه" متغیر در داخل تابع Static نوشته شده. در این مرحله باید یک شی جدید در اولین فراخوانی ایجاد شود و مقدار آن را در متغیر Static قرار دهد. این تابع در فراخوانی های بعدی باید شی ایجاد شده را فراخوانی کند.
  4. باید Constructor مربوط به کلاس و کلاسی که از آن ارث بری شده است را Private کنیم. پس از این کار دیگر قادر نخواهیم بود در خارج از کلاس از آن شی نمونه ای بسازیم و فقط این امکان در کلاس امکان پذیر است.
  5. در نهایت باید در کدهای خود به جای فراخوانی مستقیم Constructor سینگلتون (Direct calls) از تابع Static که نوشته ایم به این منظور استفاده کنیم.

نتیجه گیری

با پیاده سازی الگوی طراحی سینگلتون مشکلات مربوط به ساخت غیر ضروری شی های مربوط به یک کلاس برطرف می شود. بنابراین اگر بارها و بارها از یک شی بسازیم و به استفاده از آن نیاز داشته باشیم، فقط یک نسخه از آن شی وجود دارد که در نرم افزار فراخوانی خواهد شد. با این کار تنها همان شی در حافظه ذخیره می‌ شود و این امر باعث بهینه سازی در مصرف منابع خواهد شد. آیا شما تا کنون از الگوی طراحی Singleton در نرم افزارهای خود استفاده کرده اید؟ نظر شما در مورد اینگونه الگوهای طراحی چیست؟

متخصص PHP
اگر دوست داری برنامه نویسی PHP رو حرفه ای یاد بگیری آیا می دانید بیش از ۸۰% وب سایت های موجود در ایران از جمله لیدرهای بازار وب (اسنپ، اسنپ فود، نت برگ، دیجیکالا، الوپیک و ... ) زبان برنامه نویسی PHP را به عنوان زبان اصلی برای پیاده سازی امکانات سمت سرور خود انتخاب کردند! متخصص PHP arrow_back
7Learn Experts
comment دیدگاه کاربران
امیرمحمد رضائی replyپاسخ

سلام و درود خسته نباشید
تو سال جدید برنامه ای برای جاوا و پایتون ندارید ؟

لقمان آوند

سلام
به امید خدا برای نیمه دوم سال 98 در برنامه مون هست.

مجید زادگی replyپاسخ

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

مهدی علامه

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

یک طرفدار replyپاسخ

من بک کامنت در الگو factory زدم که مربوط به این الگو است .لطفا جا به جا کنید

Don’t use a Singleton pattern

Singleton is an anti-pattern. Paraphrased from Brian Button:

1- They are generally used as a global instance, why is that so bad? Because you hide the dependencies of your application in your code, instead of exposing them through the interfaces. Making something global to avoid passing it around is a code smell.

2- They violate the single responsibility principle: by virtue of the fact that they control their own creation and lifecycle.

3- They inherently cause code to be tightly coupled. This makes faking them out under test rather difficult in many cases.

4-They carry state around for the lifetime of the application. Another hit to testing since you can end up with a situation where tests need to be ordered which is a big no for unit tests. Why? Because each unit test should be independent from the other.

There is also very good thoughts by Misko Hevery about the root of problem.
به کد ها هم توجه کنید.

/————————————————–

//Bad:

class DBConnection
{
    private static $instance;

    private function __construct(string $dsn)
    {
        // …
    }

    public static function getInstance(): DBConnection
    {
        if (self::$instance === null) {
            self::$instance = new self();
        }

        return self::$instance;
    }

    // …
}

$singleton = DBConnection::getInstance();

//—————————————————

//Good:

class DBConnection
{
    public function __construct(string $dsn)
    {
        // …
    }

     // …
}
Create instance of DBConnection class and configure it with DSN.

$connection = new DBConnection($dsn);
//—————————————————–
//And now you must use instance of DBConnection in your application.
مهدی علامه

سلام دوست عزیز
تصحیح شد
مرسی از به اشتراک گذاشتن دیدگاهتون

add_circle ارسال دیدگاه

خوشحال میشیم دیدگاه و یا تجربیات خودتون رو با ما در میون بذارید :