Generic selectors
Exact matches only
Search in title
Search in content
Post Type Selectors

C# – תבנית העיצוב Singleton

Singleton Class
Singleton Class

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

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

Singleton Class
Singleton Class

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

יצירת Singleton Class

על מנת ליצור Singleton Class ננקוט בשלבים הבאים:

  • ה-constructor של המחלקה יוגדר כפרטי על מנת שנוכל למנוע אפשרות ליצירת מופע של המחלקה מבחוץ.
  • שדה סטטי פרטי מהטיפוס של המחלקה אשר יכיל את המופע הבודד.
  • מתודה סטטית ציבורית – ()GetInstance, אשר תחזיר את המופע הבודד.
  • שדה סטטי פרטי מסוג object בשם key אשר יכיל את המפתח לנעילת קטע הקוד הקריטי- לצורך תמיכה בריבוי תהליכים.
  • החץ מהמחלקה בחזרה אל עצמה מעיד על כך שקיים בתוך המחלקה שדה מהטיפוס  של המחלקה (שדה ה-instance)

 

על מנת לצפות דרך האתר של מייקרוסופט יש ללחוץ כאן

שעון Singleton

נחזור לדוגמת השעון שעליה דיברנו מקודם.
ניצור את מחלקת שעון לפי תרשים ה-UML שלמעלה:

public class Clock
{
    private static Clock? instance;
    private static readonly object key = new();
    private DateTime now;

    public static Clock GetInstance()
    {
        if (instance == null)
        {
            lock (key)
            {
                if (instance == null)
                    instance = new();
            }
        }
        return instance;
    }
    public void GetTime()
    {
        if (key != null)
        {
            now = DateTime.Now;
            Console.WriteLine(now.ToString());
        }
    }
}

הפונקציה GetInstance בודקת אם המופע היחיד טרם נוצר על ידי השוואה ל-null.
אם המופע טרם נוצר אז מתבצעת היצירה של המופע בפעם הראשונה, והיא מאוחסנת בשדה אשר נתנו לו את השם – instance.
אם instance לא שווה ל-null, אז יתרחש "דילוג" על יצירת המופע.
בכל נתיב אפשרי, הפונקציה תחזיר את המופע – גם אם נוצר כרגע בפעם הראשונה וגם אם היה כבר קיים.
הפונקציה GetTime מממשת את הלוגיקה שלשמה הוקמה המחלקה,
כלומר שרק באמצעות המופע היחיד של המחלקה נוכל לייבא את הזמן הנוכחי.

בעיית ריבוי תהליכים

כעת נחזור לפונקציה – GetInstance.
שימו לב שאם תהליכים אשר רצים במקביל יפעילו את הפונקציה,
אנו עלולים לקבל שני מופעים שונים.
במצב שבו עדיין לא נוצר מופע ראשוני של instance,
שני – threads הרצים במקביל יגיעו לשורת הקוד:


     if (instance == null) 

התשובה ששניהם יקבלו מהתנאי תהיה – true, משום שלא נוצר עדיין מופע.
לכן שני ה-threads יגיעו במקביל לשורה שמייצרת מופע, מה שיגרום שייווצרו שני מופעים בכל זאת.
נעילת קטע הקוד במקטע קריטי המטפל ביצירת המופע תבטיח שרק thread אחד בלבד יוכל לבצע קוד זה ברגע נתון.
כלומר שננעל באמצעות – key את המקטע הקריטי,
ובכך נבטיח שמופע יחיד בלבד יוכל להיווצר ממחלקת שעון.

*שימו לב לשדה הסטטי הפרטי – key שיצרנו, הוא סטטי מכיוון שהמתודה סטטית.


private static readonly object key = new();


lock (key)
{
    if (instance == null)
    instance = new();
}   

קריאה ל-Singleton 

לאחר שיצרנו את המחלקה, בכל פעם שנרצה לפנות למופע ה-Singleton נשתמש בפונקציה – GetInstance, כאשר זו תיצור את המופע רק בפעם הראשונה שנפנה אליה, כלומר שנצפה לקבל מופע זהה בכל פעם שנפנה לפונקציה זו גם לאחר מכן:


Clock.GetInstance().GetTime();

ולאחר שנריץ את התוכנית נקבל את הפלט הבא:

 Singleton Clock Output
Singleton Clock Output

אהבתכם את המדריך? פתר לכם תקלה? הזמינו את כותב המדריך לכוס קפה

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

ניתן לתרום 10, 15, 20 או כל סכום אחר שתרצו באמצעות כרטיס אשראי \ Paypal

רוצים לשתף את המדריך?

כתיבת תגובה

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

הזמינו אותי לכוס קפה
buy me coffee

אהבתכם את המדריך? פתר לכם תקלה? הזמינו את כותב המדריך לכוס קפה

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