תבנית Singleton
חלק מהיחידה תכנות מונחה עצמים במסלול ה-Java של Coddy. שיעור 65 מתוך 87.
תבנית Singleton היא תבנית עיצוב ליצירת אובייקטים שמבטיחה שלמחלקה יהיה מופע אחד בלבד לאורך כל היישום שלך, ובמקביל מספקת נקודת גישה גלובלית למופע הזה. היא שימושית עבור משאבים שכדאי לשתף, כמו מנהלי תצורה, מאגרי חיבורים או שירותי רישום.
התבנית פועלת על ידי הפיכת הבנאי לפרטי, וכך נמנעת יצירה ישירה של מופעים. במקום זאת, מתודה סטטית שולטת בגישה למופע היחיד:
public class DatabaseConnection {
private static DatabaseConnection instance;
// בנאי פרטי מונע יצירת מופע ישירות
private DatabaseConnection() {
System.out.println("Connection created");
}
// נקודת גישה גלובלית
public static DatabaseConnection getInstance() {
if (instance == null) {
instance = new DatabaseConnection();
}
return instance;
}
public void query(String sql) {
System.out.println("Executing: " + sql);
}
}כל קריאה ל־getInstance() מחזירה את אותו אובייקט. המופע נוצר רק כאשר מבקשים אותו לראשונה. זה נקרא אתחול עצל:
DatabaseConnection db1 = DatabaseConnection.getInstance();
DatabaseConnection db2 = DatabaseConnection.getInstance();
System.out.println(db1 == db2); // true - אותו מופעהמרכיבים העיקריים של Singleton הם: שדה private static שמחזיק את המופע, בנאי private ומתודה public static שמחזירה את המופע. השילוב הזה מבטיח שלא משנה כמה פעמים תבקשו את האובייקט, תמיד תקבלו את אותו האובייקט.
אתגר
קלבואו נבנה מנהל תצורה ליישום באמצעות תבנית Singleton! מנהל התצורה שלך יבטיח שכל חלקי היישום ישתפו את אותן הגדרות, בלי קשר למספר הפעמים שבהן הם מבקשים גישה אליו.
תארגן את הקוד שלך בשני קבצים:
AppConfig.java: צור מחלקת Singleton שמנהלת את הגדרות התצורה של היישום. למחלקהAppConfigשלך צריכים להיות:שדה סטטי פרטי שמחזיק את המופע היחיד.
שדה פרטי מסוג String בשם
appNameושדה פרטי מסוג int בשםmaxUsers.בנאי פרטי שמאתחל את
appNameל-"MyApplication"ואתmaxUsersל-100, ואז מדפיס אתAppConfig initialized.מתודה סטטית ציבורית
getInstance()שיוצרת את המופע רק אם הוא עדיין לא קיים (אתחול עצל), ואז מחזירה אותו.מתודה
setAppName(String name)שמעדכנת את שם היישום.מתודה
setMaxUsers(int max)שמעדכנת את מספר המשתמשים המרבי.מתודה
displaySettings()שמדפיסהApp: [appName], Max Users: [maxUsers].Main.java: הדגם שה-Singleton שלך פועל כראוי! יתקבלו שני קלטים: שם יישום חדש (String) וערך חדש למספר המשתמשים המרבי (מספר שלם).תחילה, קבל מופע של
AppConfigושמור אותו במשתנה בשםconfig1. קרא ל-displaySettings()כדי להציג את ערכי ברירת המחדל.לאחר מכן, עדכן את ההגדרות באמצעות ערכי הקלט שלך על ידי קריאה ל-
setAppNameול-setMaxUsersב-config1.קבל מופע נוסף ושמור אותו ב-
config2. קרא ל-displaySettings()ב-config2כדי להוכיח שהוא משקף את השינויים שבוצעו באמצעותconfig1.לבסוף, הדפס האם שתי ההפניות מצביעות על אותו אובייקט:
Same instance: [true/false], באמצעות השוואה ביןconfig1 == config2.
יתקבלו שני קלטים לפי הסדר: שם היישום החדש (String) ומספר המשתמשים המרבי החדש (מספר שלם).
האתגר הזה מדגים את היתרון המרכזי של תבנית Singleton: לא משנה כמה פעמים תבקש את התצורה, תמיד תקבל את אותו מופע עם אותו מצב משותף!
נסו בעצמכם
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// קרא את הקלטים
String newAppName = scanner.nextLine();
int newMaxUsers = scanner.nextInt();
// TODO: קבל את המופע הראשון של AppConfig ושמור אותו ב-config1
// TODO: קרא ל-displaySettings() על config1 כדי להציג את ערכי ברירת המחדל
// TODO: עדכן את ההגדרות באמצעות setAppName ו-setMaxUsers על config1
// TODO: קבל מופע נוסף ושמור אותו ב-config2
// TODO: קרא ל-displaySettings() על config2 כדי להוכיח שהשינויים משותפים
// TODO: הדפס האם שתי ההפניות מצביעות על אותו אובייקט:
// "Same instance: [true/false]" באמצעות config1 == config2
}
}
השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.
כל השיעורים ביחידה תכנות מונחה עצמים
1יסודות התכנות מונחה העצמים
קבצים חיצונייםמבוא לתכנות מונחה עצמיםמחלקות לעומת אובייקטיםמילת המפתח thisמתודותשדות (מאפיינים)מתודת הבנאיהעמסת בנאיםחזרה – מחשבון פשוט4ירושה
ירושה בסיסית (extends)מילת המפתח superדריסת מתודות (@Override)שרשור בנאיםהמחלקה Objectירושה יחידה ורב־רמתיתלמה אין ירושה מרובה של מחלקותסיכום – היררכיית עובדים7מתודות מיוחדות ומחלקת Object
מתודת toString()equals() ו-hashCode()מתודת clone()compareTo() ו-Comparableהממשק Comparatorסיכום – מיון מותאם אישית2מצייני גישה ואנקפסולציה
סקירה של רמות הגישהמתודות Getter ו-Setterהסתרת מידעמילת המפתח finalסיכום – מנהל חשבון בנק5פולימורפיזם
יסודות העמסת מתודותדריסת מתודות (בזמן ריצה)המרה כלפי מעלה וכלפי מטההאופרטור instanceofמחלקות ומתודות מופשטותסיכום – מחשבון צורות8מושגי OOP מתקדמים
הרכבה מול ירושהאגרגציה מול הרכבהמחלקות פנימיות, מקוננות ואנונימיותEnums ומתודות של EnumRecords (Java 16+)מחלקות חתומות (Java 17+)11תבניות עיצוב חלק 1
מבוא לתבניות עיצובתבנית Singletonתבנית Factoryתבנית Builderתבנית Observerתבנית Strategy3מאפייני מחלקה וחברים סטטיים
משתני מופע לעומת משתנים סטטייםמתודות סטטיותבלוקים סטטייםקבועים (static final)סיכום — מונה ומחלקת עזר6ממשקים ומחלקות מופשטות
מבוא לממשקיםמימוש ממשקיםמימוש של כמה ממשקיםמתודות ברירת מחדל וסטטיות בממשקמחלקות מופשטות לעומת ממשקיםממשקים פונקציונלייםסיכום – מערכת תשלומיםתרגלו בעצמכם: קומפיילר Java אונליין