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

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

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

כיצד פועלת דפוס עיצוב הדקורטור?

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

לתבנית עיצוב טיפוסית יש את המבנה הבא:

מתרשים הכיתתי למעלה ניתן לראות שלתבנית הדקורטור יש ארבע כיתות עיקריות.

רְכִיב: זהו מחלקה מופשטת (או ממשק), המשמשת כסוג-על לדפוס המעצב.

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

instagram viewer

מְעַצֵב: מחלקה זו מופשטת ויש לה אותו טיפוס על כמו האובייקט שהיא תקשט. בתרשים המחלקה, תראה שני מערכות יחסים בין כיתות הרכיבים והמעצבים. מערכת היחסים הראשונה היא מערכת יחסים של ירושה; כל מעצב הוא רְכִיב. הקשר השני הוא של קומפוזיציה; כל מעצב יש (או עוטף א) רכיב.

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

הטמעת דפוס עיצוב הדקורטור ב-Java

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

פּוּמְבֵּימִמְשָׁקפיצה{
פּוּמְבֵּיתַקצִיר חוּט תיאור();
פּוּמְבֵּיתַקצִירלְהַכפִּילעֲלוּת();
}

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

פּוּמְבֵּימעמדשמרים קרוסט פיצהמיישםפיצה{
@עקוף
פּוּמְבֵּי חוּט תיאור(){
לַחֲזוֹר"בצק פיצה עם שמרים";
}

@עקוף
פּוּמְבֵּילְהַכפִּילעֲלוּת(){
לַחֲזוֹר18.00;
}
}

ה-YeastCrustPizza הוא הבטון הראשון שיעור Java של ממשק פיצה. סוג הפיצה השני הזמין הוא לחם שטוח:

פּוּמְבֵּימעמדFlatbreadCrustPizzaמיישםפיצה{
@עקוף
פּוּמְבֵּי חוּט תיאור(){
לַחֲזוֹר"בצק פיצה עשוי מלחם שטוח";
}

@עקוף
פּוּמְבֵּילְהַכפִּילעֲלוּת(){
לַחֲזוֹר15.00;
}
}

מחלקת FlatbreadCrustPizza היא הרכיב הקונקרטי השני, ובדומה למחלקה YeastCrustPizza, היא מיישמת את כל הפונקציות המופשטות של ממשק Pizza.

המעצבים

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

פּוּמְבֵּיתַקצִירמעמדToppingDecoratorמיישםפיצה{
פּוּמְבֵּי חוּט תיאור(){
לַחֲזוֹר"תוספת לא ידועה";
}
}

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

תוספת גבינה

פּוּמְבֵּימעמדגבינהמשתרעToppingDecorator{
פְּרָטִי פיצה פיצה;

פּוּמְבֵּיגבינה(פיצה פיצה){
זֶה.פיצה = פיצה;
}

@עקוף
פּוּמְבֵּי חוּט תיאור(){
לַחֲזוֹר pizza.description() + ", תוספת גבינה";
}

@עקוף
פּוּמְבֵּילְהַכפִּילעֲלוּת(){
לַחֲזוֹרפיצה.עֲלוּת() + 2.50;
}
}

תוספת פפרוני

פּוּמְבֵּימעמדפֶּפֶּרוֹנימשתרעToppingDecorator{
פְּרָטִי פיצה פיצה;

פּוּמְבֵּיפֶּפֶּרוֹני(פיצה פיצה){
זֶה.פיצה = פיצה;
}

@עקוף
פּוּמְבֵּי חוּט תיאור(){
לַחֲזוֹר pizza.description() + ", תוספת פפרוני";
}

@עקוף
פּוּמְבֵּילְהַכפִּילעֲלוּת(){
לַחֲזוֹרפיצה.עֲלוּת() + 3.50;
}
}

ציפוי פטריות

פּוּמְבֵּימעמדפטרייהמשתרעToppingDecorator{
פְּרָטִי פיצה פיצה;

פּוּמְבֵּיפטרייה(פיצה פיצה){
זֶה.פיצה = פיצה;
}

@עקוף
פּוּמְבֵּי חוּט תיאור(){
לַחֲזוֹר pizza.description() + ", ציפוי פטריות";
}

@עקוף
פּוּמְבֵּילְהַכפִּילעֲלוּת(){
לַחֲזוֹרפיצה.עֲלוּת() + 4.50;
}
}

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

פּוּמְבֵּימעמדרָאשִׁי{
פּוּמְבֵּיסטָטִיבָּטֵלרָאשִׁי(מחרוזת[] args){
פיצה פיצה1 = חָדָשׁ YeastCrustPizza();
פיצה1 = חָדָשׁ פפרוני (פיצה1);
פיצה1 = חָדָשׁ גבינה (פיצה1);
System.out.println (pizza1.description() + " $" + pizza1.cost());
}
}

הפעלת קוד זה תפיק את הפלט הבא במסוף:

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

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

פיצה פיצה2 = חָדָשׁ YeastCrustPizza();
פיצה2 = חָדָשׁ פפרוני (פיצה2);
פיצה2 = חָדָשׁ גבינה (פיצה2);
פיצה2 = חָדָשׁ גבינה (פיצה2);
פיצה2 = חָדָשׁ פטריות (פיצה2);

System.out.println (pizza2.description() + " $" + pizza2.cost());

האפליקציה המעודכנת תפיק את הפלט הבא במסוף:

היתרונות של שימוש בתבנית עיצוב הדקורטור

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

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