715
1

מסבירים את תבנית העיצוב Singleton

715
זמן קריאה: 3 דקות

בואו נדבר על סינגלטון, מדובר בתבנית פשוטה יחסית, נפוצה אך גם שנוייה במחלוקת.

האם אתם משתמשים בתבנית העיצוב Singleton? סביר להניח שכן או לכל הפחות השתמשתם בעבר
מראיינים רבים יצפו מכם להכיר את התבנית ולא יסלחו לכם אם יצטרכו להסביר לכם מה זה.

אז מה זה בכלל Singleton? איזה בעיה זה פותר? מה היתרונות / חסרונות שלו? וכמה זה עולה לנו?

תוכן עניינים

רקע

Singleton היא תבנית עיצוב (שייכת לקבוצת creational patterns) המאפשרת לך להבטיח שלמחלקה יש מופע אחד בלבד תוך מתן נקודת גישה גלובלית למופע זה.

בגישה הקלאסית שאנו מכירים מי שיוצר את המופע של המחלקה היא מחלקה אחרת שמפעילה את הבנאי (Constructor), בגישה זו אנו יכולים כמובן ליצור את אותה המחלקה כמה פעמים שנרצה או נצטרך.
תבנית העיצוב של סינגלטון הופכת את המחלקה לאחראית על יצירת המופע של עצמה ושולטת במופע שנוצר בדרך שתבטיח שאובייקט זה לעולם לא יווצר יותר מפעם אחת.

אלגוריתם סינגלטון

  1. הוסף משתנה סטטי פרטי למחלקה שישמש אחסון למופע המחלקה
  2. הוסף מתודה “Get Instance” סטטית שתחזיר את המופע שנוצר ורק במידה והוא עדיין לא קיים (null) אז תקרא לבנאי שייצור אותו ולאחר מכן תחזיר
  3. הכרז על הבנאי אך הפוך את הרשאותיו לפרטי, כדי שלא יוכלו ליצור / להשתמש בו מבחוץ.

מימוש בקוד #C

 

				
					public class Singleton
    {
        private Singleton() 
        { 
            // do something
        }
        private static Singleton _instance;
        
        public static Singleton GetInstance()
        {
            if (_instance == null)
            {
                _instance = new Singleton();
            }
            return _instance;
        }

        public static void func1()
        {
            // ...
        }
        
        public static void func2()
        {
            // ...
        }
    }
				
			

הקוד שמעל הטקסט זה בעצם מימוש קלאסי של סינגלטון
הקוד שבהמשך הוא דוגמא לשימוש במחלקה הזו באיזשהו מקום שתצטרכו באפליקציה שלכם:

				
					public class Program
    {
        static void Main(string[] args)
        {
            Singleton s1 = Singleton.GetInstance();
            Singleton s2 = Singleton.GetInstance();

            if (s1 == s2)
            {
                Console.WriteLine("Singleton works, s1 and s2 contain the same instance.");
            }
            else
            {
                Console.WriteLine("Singleton failed, s1 and s2 contain different instances.");
            }
        }
    }
				
			

מתי נצטרך להיזהר בשימוש של סינגלטון?

שאנו מגדירים אובייקט להיות סינגלטון אנו בעצם מגדירים שהוא יהיה מוכר בכל היקף האפליקציה ושנוכל לגשת אליו מכל מקום בקוד ובכל עת, הדוגמא הנפוצה ביותר לשימוש כזה הוא לוגר, אנו צריכים רק אחד כזה ונרצה להשתמש בו בהרבה מאוד מקומות.
עד עתה זה נשמע טוב מידי, אז מה בכל זאת הבעיה עם סינגלטון? 

סינגלטון ו-Multi threads 

סינגלטון לא בטוח בעבודה עם Threads, לפחות לא במימוש המקורי (ישנה הרחבה שפותרת את זה בשפות מסויימות)
תחשבו על כך ששני Threads רצים במקביל ומנסים ליצור את האובייקט בפעם הראשונה, יכול להיווצר מצב בו נוצרים שני מופעים של אותו אובייקט וזה בדיוק מה שהסינגלטון מנסה למנוע.

סינגלטון הוא האוייב הגדול של ה Unit-tests

אחד החסרונות הגדולים של הסינגלטון שהוא מקשה מאוד על בדיקות יחידה,
בבדיקות יחידה אנו נרצה תמיד כמה שפחות תלויות בין מחלקות ואם כבר יש תלות כזו אז שתהיה מסופקת באופן אידיאלי על ידי הקונסטרקטור או על ידי Setters (כדי שנוכל לעשות להם Mock בקלות)
התלות שהסינגלטון יוצר מביא איתו השלכות חמורות שצריך לחשוב עליהן בעת הבדיקות:

  • סדר הטסטים של כל מי שמשתמש בסינגלטון קריטי (יוצר תלות בין הטסטים וכבר לא בדיקת יחידה)
  • קריאות מרובות של אותה בדיקה יכולות להניב תוצאות שונות.
  • לא ניתן להריץ בדיקות במקביל.
    בשיטת פיתוח ללא שימוש בסינגלטון אנו נכניס  
סינגלטון בזבזן זיכרון

בשפות בהן יש Garbage Collector, השפה דואגת לשמור את האובייקט כחשוב בזיכרון (בגלל כל החלקים הסטטיים) ולא משחררת אותו

סיכום

למרות שתבנית העיצוב מפורסמת ופופולרית, יש לה חסרונות רבים ושמדברים על קוד גדול אלה חסרונות קריטיים שיהפכו עם הזמן לקוף על הגב שיהיה קשה להוריד.
למרבה המזל עם הזמן הם הופכים להיות מוכרים יותר ויותר עד כדי כך שבמקומות רבים כבר לא מגדירים אותו כתבנית עיצוב אלא Anti Pattern

מקורות וקרדיטים

Head First Design Patterns book – ספר מעולה!
Wikipedia – https://en.wikipedia.org/wiki/Singleton_pattern
Business photo created by freepik – www.freepik.com


 

אמיר שטיימן
WRITEN BY

אמיר שטיימן

Backend Engineer @Cynet
ביום יום מפתח Backend בסביבת SaaS, מיקרו סרביסים בשילוב של מערכות מבוזרות. בזמני הפנוי - לומד ומשתדרג בעולם התוכנה, אוהד מכבי חיפה, פלייסטיישן ובירה עם חברים :)
Linkedin | Twitter

One thought on “מסבירים את תבנית העיצוב Singleton

  1. תודה רבה!
    הבהיר לי בצורה ברורה מה זה סינגלטון, ולמה לא להשתמש בו 🙂

כתיבת תגובה

האימייל לא יוצג באתר. שדות החובה מסומנים *