קומפוזיציה, צבירה ואסוציאציה בג'אווה

1. הקדמה

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

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

2. קומפוזיציה

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

לחלופין, לעתים קרובות אנו קוראים לזה מערכת יחסים "יש- a" (בניגוד ליחסי "זה- a", שהוא ירושה).

לדוגמא, חדר שייך לבניין, או במילים אחרות לבניין יש חדר. אז בעצם, בין אם אנחנו קוראים לזה "שייך" או "יש- a" זה רק עניין של נקודת מבט.

קומפוזיציה היא סוג חזק של יחסי "יש- a" מכיוון שהאובייקט המכיל הוא הבעלים של זה. לָכֵן, מחזורי החיים של האובייקטים קשורים. המשמעות היא שאם נשמיד את חפץ הבעלים, גם חבריו יושמדו איתו. לדוגמה, החדר נהרס עם הבניין בדוגמה הקודמת שלנו.

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

במונחים של קרדינליות, לאובייקט המכיל יכול להיות כמה חלקים שאנחנו רוצים. למרות זאת, לכל החלקים צריך להיות מיכל אחד בדיוק.

2.1. UML

ב- UML אנו מציינים קומפוזיציה עם הסמל הבא:

שים לב, שהיהלום נמצא באובייקט המכיל והוא בסיס הקו, לא ראש חץ. לשם הבהירות, לעתים קרובות אנו מציירים גם את ראש החץ:

אז נוכל להשתמש בבניית UML זו לדוגמא חדר הבניין שלנו:

2.2. קוד מקור

בג'אווה נוכל לדגמן זאת עם מעמד פנימי לא סטטי:

בניין כיתה {חדר כיתה {}}

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

בניין מחלקה {Room createAnonymousRoom () {החזר חדר חדש () {@Override void doInRoom () {}}; } חדר createInlineRoom () {class InlineRoom מיישם חדר {@Override void doInRoom () {}} להחזיר InlineRoom חדש (); } Room createLambdaRoom () {return () -> {}; } ממשק חדר {void doInRoom (); }}

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

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

בניין כיתה {חדרי רשימה; כיתה {} }

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

בניין כיתה {כתובת מחרוזת; חדר כיתה {String getBuildingAddress () {return Building.this.address; }}}

3. צבירה

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

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

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

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

3.1. UML

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

לכן גם ייצוגי UML דומים מאוד. ההבדל היחיד הוא שהיהלום ריק:

במכוניות וגלגלים היינו:

3.2. קוד מקור

בג'אווה, אנו יכולים לדגם צבירה עם הפניה ישנה רגילה:

גלגל מחלקה {} מכונית מחלקה {גלגלים ברשימה; }

החבר יכול להיות בכל סוג של מעמד, למעט מעמד פנימי לא סטטי.

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

מכונית מחלקה {גלגלים ברשימה; גלגל מחלקה סטטי {}}

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

גלגל כיתה {מכונית לרכב; } מכונית מחלקה {גלגלים ברשימה; }

4. עמותה

האסוציאציה היא היחסים החלשים ביותר בין השלושה. זה לא קשר "יש-יש", אף אחד מהאובייקטים אינו חלקים או חברים באחר.

אסוציאציה פירושה רק שהאובייקטים "מכירים" זה את זה. לדוגמא, אמא וילדה.

4.1. UML

ב- UML נוכל לסמן שיוך עם חץ:

אם האסוציאציה היא דו כיוונית, נוכל להשתמש בשני חצים, חץ עם ראש חץ בשני הקצוות או קו ללא ראשי חץ:

אנו יכולים לייצג אם וילדה ב- UML, ואז:

4.2. קוד מקור

בג'אווה נוכל לדגם שיוך באותה צורה כמו צבירה:

כיתה ילד {} כיתה אם {רשימת ילדים; }

אבל חכה, איך נוכל לדעת אם התייחסות פירושה צבירה או שיוך?

ובכן, אנחנו לא יכולים. ההבדל הוא רק הגיוני: האם אחד האובייקטים הוא חלק מהאחר או לא.

כמו כן, עלינו לשמור על ההפניות באופן ידני בשני הקצוות כפי שעשינו עם הצבירה:

ילד בכיתה {אם אמא; } אם בכיתה {רשימת ילדים; }

5. UML Sidenote

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

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

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

6. דוגמה מורכבת

בואו נראה דוגמה (קצת יותר) מורכבת!

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

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

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

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

כתוצאה מכך, אנו יכולים לדגמן דוגמה זו באמצעות דיאגרמת ה- UML הבאה:

וקוד Java נראה כך:

מחלקה אוניברסיטאית {מחלקת רשימה; } מחלקה בכיתה {פרופסורים לרשימה; } פרופסור בכיתה {מחלקת רשימה; רשימת חברים; }

שים לב, שאם אנחנו להסתמך על המונחים "יש- a", "שייך ל", "חבר של", "חלק של"וכן הלאה, אנו יכולים לזהות ביתר קלות את היחסים בין האובייקטים שלנו.

7. מסקנה

במאמר זה ראינו את המאפיינים והייצוג של הרכב, צבירה ואסוציאציה. ראינו גם כיצד לעצב מערכות יחסים אלה ב- UML וב- Java.

כרגיל, הדוגמאות זמינות ב- GitHub.


$config[zx-auto] not found$config[zx-overlay] not found