الگوی طراحی singleton در جاوا اسکریپت

الگوی طراحی singleton در جاوا اسکریپت نوشته شده در   javascript ۱۰ مهر , ۱۳۹۷ توسط  عباس حسینی

singleton design pattern یکی از ساده ترین الگو های طراحی GOF میباشد و ایده اصلی این الگو این است که هر کلاس باید مسئول ساخته شدن شی از خودش باشد و اجازه ندارد بیشتر از یک بار شی بسازد در ادامه به توضیح کامل این الگو خواهم پرداخت

لیست مطالب

تعریف الگوی طراحی singleton در جاوا اسکریپت

طبق تعریف الگوی singleton میگه که از هر کلاس فقط و فقط باید یک شی ساخته بشه و بصورت global برای دیگران قابل دسترسی باشه

ممکنه این سوال برای شما پیش بیاد که یعنی چی که از یک کلاس نمیشه بیشتر از یک شی ساخت ؟
الگوی طراحی singleton
در پاسخ باید بگم که یعنی پیاده سازی کد جوریه که به ما اجازه نمیده فرآیند ساخت شی بیشتر از یکبار صورت بگیره

سوال بعدی که ممکنه ذهن شما رو درگیر خودش بکنه اینه که شی ساخته شده به صورت global در اختیار بقیه قرا میگیره یعنی چی ؟

این سوال بسیار مهمه چون باید دقت کنید که فرآیند ساخت شی بصورت private و یکبار انجام میشه و دسترسی به شی ساخته شده از طریق یک متد یا تابعی است که کد در اختیار ما میزاره

روند کار هم به این شکل است که وقتی نیاز به شی singleton داریم شی مورد نظر رو از طریق آن تابع واسط درخواست میدیم اگر موجود بود به دست ما میرسه اگر نه یکبار ساخته میشه و بعد به دست ما میرسه بعد از این هر کسی اون شی رو درخواست بده همونی رو بدست میاره که بار اول ساخته شده

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

چطور میشه الگوی singleton رو در جاوا اسکریپت پیاده سازی کرد ؟

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

قبل از هر چیز برای پیاده سازی الگوی singleton باید به چند نکته توجه کنید
از هر کلاس،فقط میشه یک شی ساخت
فرآیند ساخت شی private است
شی ساخته شده بصورت global در اختیار بقیه قرار میگیرد

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

از طریق global variable و literal : به این صورت که یک object literal بصورت global داریم که بقیه به آن دسترسی دارند برای فهم بهتر آن به کد زیر توجه کنید


var singletonInstance = {
    name : 'abbas',
    family : 'hosseini'
}

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

از طریق global variable و  class: در این روش به جای literal object از کلاس استفاده میشود و فرآیند ساخت شی توسط خود کلاس مدیریت میشود و همانطور که در کد زیر میبینید در سازنده کلاس Info با استفاده از شرط singletonInstance != null اجازه ساخت شی را بیشتر از یکبار نمیدهد و شی singleInstance برای همه قابل دسترس بوده ضمن اینکه فرآیند ساخت شی بصورت کپسوله توسط کلاس انجام میشود بنابراین singleInstance یک شی singleton میباشد


var singletonInstance = null;
class Info{
    constructor (){
        if(singletonInstance != null) {
            this.name= 'abbas';
            this.family = 'hosseini'
            singletonInstance = this
        }
    }
}
var myInstance = new Info()

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

لینک مطالعه

در این روش closure به ما کمک میکنه که فرآیند ساخت شی رو کپسوله کنیم و این کار از طریق الگوی IFFE براحتی امکانپذیر میباشد که در کد زیر نمونه ای از آن را مشاده میکنید



/**
* Singleton Design Pattern
* Using IFFE pattern encapsulate Info class
*/
var Singleton = (function(){

    var instance = null;

    /**
     * @class {Info} is a class that we want instatiate signleton
     */
    class Info {
        constructor (){
            this.name = 'abbas';
            this.family = 'hosseini';

        }
    }

    return {
        /**
         * @method {getInstnace} is a public api for getting singleton instance
         */
        getInstnace : function (){
            /**
             * This condition ensure that Info calss instantiate just one time
             */
            if(instance == null) {
                instance = new Info();
            }
            return instance
        }
    }
    
})()

console.log(Singleton.getInstnace())
console.log(Singleton.getInstnace())

نتیجه اجرای کامل این الگو در ادامه قابل مشاهده میباشد

See the Pen
Javascript – Singleton Pattern
by abbas hosseini (@abizebel)
on CodePen.

با دقت کردن به کد بالا میتوان موارد زیر را نتیجه گیری کرد :

۱- یک کلاس به نام Info داریم که قرار است از آن شی singleton بسازیم و از IFFE pattern  و خاصیت closure برای کپسوله کردن فرآیند ساخت شی استفاده شده است

۲- تابع getInstance به عنوان یک public api وظیفه ساختن شی singleton را به عهده میگیرد و هر کسی میتوان با استفاده از آن به شی singleton دسترسی پیدا کند

۳ – داخل متد getInstnace یک شرط وجود دارد که از دوباره ساخته شدن شی از کلاس Info جلوگیری میکند

بنابراین سه اصل مربوط به پیاده سازی الگوی  singleton  در این کد رعایت شده است

حال در انتها بعد از اجرای console.log(Singleton.getInstnace()) چه اتفاقی میفتد ؟

از آنجایی که این الگوی  singleton است وقتی متد getInstnace فراخوانی میشود ، شرط if(instance == null) چک میشود اگر برای اولین بار صدا زده شود چون مقدار متغیر instance خالی میباشد شرط برقرار شده و یک شی از کلاس  Info ساخته شده و به متغیر instnace تخصیص داده میشود

اما بعد از آن هر بار متد getInstnace فراخوانی شود چون متغیر instance دیگر برابر مقدار خالی نیست و تبدیل به یک closure شده که مقدار شی singleton در آن قرار دارد بنابراین همان شی قبلی را برمیگرداند

چرا instance یک  closure است ؟

چون تابع getInstnace به یک متغیر خارج از اسکوپ خود به نام instance  اشاره کرده بنابراین طبق قائده closure اسکوپ مربوط به متغیر instance از بین نرفته و هر گاه تابع getInstnace فراخوانی شود به آن دسترسی دارد

موارد استفاده از الگوی singleton در جاوا اسکریپ

بطور کلی زمانی از از الگوی singleton استفاده میکنیم که مطمئن هستیم ، از یک شی فقط یکبار باید ساخته شود و توسط بقیه مورداستفاده قرار میگیرد ، در عمل یکی از بهترین مثال هایی که میتونم بیان کنم پیاده سازی lifecyle از نوع singleton در یک ioc container است

لیست الگوهای طراحی GOF در جاو اسکریپت

 

Creational Patterns

 

Structural Patterns

 

Behavioral Patterns