singleton چیست؟ آموزش الگوی طراحی سینگلتون با مثال عملی

سطح مقاله: پیشرفته
زمان مطالعه: 10 دقیقه
۲۵ آبان ۱۳۹۸
فارسی
الگوی طراحی سینگلتون
English
Singleton Design Pattern

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

فهرست محتوای این مقاله

singleton چیست؟

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

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

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

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

اما شاید برای شما جای سوال باشد که چرا باید تعداد نمونه های یک کلاس بیشتر از یکی نباشد؟ رایج ترین دلیل این امر کنترل دسترسی به برخی از منابع مشترک (Shared Resources) است. زیرا هر یک از این اشیای ساخته شده بخشی از منابع را به خود اختصاص می‌دهند. تصور کنید که شما یک شی از یک کلاس را ایجاد کرده‌اید، اما بعد از مدتی تصمیم به ایجاد یک شی دیگر از آن کلاس می‌گیرید.

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

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

تعریف singleton

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

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

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

معمولا در در نرم‌افزارها وظیفه برقراری ارتباط با دیتابیس را بر عهده یک شی قرار می‌دهند. بنابراین برای اینکه مطمئن شویم نمونه ها و شی های دیگری برای انجام این کار از کلاس ایجاد نمی‌شوند، بهترین کار استفاده از الگوی طراحی 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 که نوشته‌ایم به این منظور استفاده کنیم.
<?php
/*
* DBConnection class - only one connection alowed
*/
class DBConnection {
	private $connection;
	private static $instance; //The static variable for store Singleton's instance
	private $host = "HOSTt";
	private $username = "USERNAME";
	private $password = "PASSWORd";
	private $database = "DATABASE";
	/*
	Get an instance of the DBConnection 
	@return Instance
	*/
	public static function getInstance():DBConnection {
		if(self::$instance==null) { // If no instance then make one
			$instance=self::$instance = new DBConnection ();
		}
		return $instance;
	}
	// Constructor
	private function __construct() {
		$this->connection = new mysqli($this->host, $this->username, 
			$this->password, $this->database);
	}
}
?>

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

نتیجه گیری

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

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

چه امتیازی به این مقاله می دید؟
نویسنده
عاشق برنامه نویسی و نوشتن ...

نظرات کاربران

vahid almasi

فک کنم داخل مثال اول یه مشکلی کوچیک هستش

F Y

مرسی از سایت خوبتون و اینکه رایگان مقاله میذارین

یک طرفدار

من بک کامنت در الگو 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.
مهدی علامه

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

مجید زادگی

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

مهدی علامه

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

امیرمحمد رضائی

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

لقمان آوند

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

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

 
گزارش مشکل