מבוא לתבניות עיצוב
חלק מהיחידה תכנות מונחה עצמים במסלול ה-C++ של Coddy. שיעור 90 מתוך 104.
תבניות עיצוב הן פתרונות מוכחים לשימוש חוזר לבעיות נפוצות שמתעוררות בתכנון תוכנה. הן אינן קוד שמעתיקים ישירות — הן תבניות או שרטוטים שמתארים כיצד לארגן מחלקות ואובייקטים כדי לפתור אתגרים מסוימים באלגנטיות.
המושג זכה לפופולריות בזכות "כנופיית הארבעה" (GoF) בספרם משנת 1994, שבו קטלגו 23 דפוסי תכנון בסיסיים. דפוסים אלה מקובצים בדרך כלל לשלוש קטגוריות:
| קטגוריה | מטרה | דוגמאות |
|---|---|---|
| יצירה | מנגנוני יצירת אובייקטים | Singleton, Factory, Builder |
| מבנית | הרכבה של מחלקות ואובייקטים | Adapter, Decorator, Composite |
| התנהגותית | אינטראקציה ואחריות של אובייקטים | Observer, Strategy, Command |
למה ללמוד תבניות עיצוב? הן מספקות אוצר מילים משותף למפתחים — האמירה "השתמשו כאן ב-Factory" מעבירה מיד רעיון מורכב. הן גם עוזרות לך להימנע מהמצאת פתרונות מחדש ולהפוך את הקוד שלך לגמיש יותר וקל יותר לתחזוקה.
ב-C++, דפוסי עיצוב מנצלים את תכונות התכנות מונחה העצמים שכבר למדת: ירושה, פולימורפיזם, מחלקות מופשטות ותבניות. בשיעורים הבאים תיישם כמה דפוסים חיוניים ותבין מתי כל אחד מהם הוא הכלי המתאים למשימה.
אתגר
קלבואו נבנה מסווג תבניות פשוט שידגים את ההבנה שלך בשלוש הקטגוריות של תבניות עיצוב. תיצור מערכת שמקבלת שם של תבנית ומזהה לאיזו קטגוריה היא שייכת — Creational, Structural או Behavioral — לצד תיאור קצר של מטרת הקטגוריה.
תארגן את הקוד שלך בשלושה קבצים:
PatternCategory.h: הגדר מחלקת בסיס מופשטת בשםPatternCategoryשמייצגת קטגוריה של תבניות עיצוב. היא צריכה לכלול:- מתודה וירטואלית טהורה
getName()שמחזירה את שם הקטגוריה כמחרוזת - מתודה וירטואלית טהורה
getPurpose()שמחזירה תיאור של מה שהתבניות בקטגוריה הזאת עושות - הורס וירטואלי
לאחר מכן, צור שלוש מחלקות נגזרות שיורשות מ-
PatternCategory:CreationalCategory: מחזירה את השם"Creational"ואת המטרה"Object creation mechanisms"StructuralCategory: מחזירה את השם"Structural"ואת המטרה"Class and object composition"BehavioralCategory: מחזירה את השם"Behavioral"ואת המטרה"Object interaction and responsibility"
- מתודה וירטואלית טהורה
PatternClassifier.h: צור מחלקהPatternClassifierשיכולה לזהות לאיזו קטגוריה שייכת תבנית נתונה.המסווג שלך צריך לכלול מתודה
classifyשמקבלת שם של תבנית (מחרוזת) ומחזירה מצביע ל-PatternCategoryהמתאימה. השתמש במצביעים חכמים (std::unique_ptr) לניהול הזיכרון.המסווג צריך לזהות את התבניות הבאות:
- Creational:
Singleton,Factory,Builder - Structural:
Adapter,Decorator,Composite - Behavioral:
Observer,Strategy,Command
אם שם התבנית אינו מזוהה, החזר
nullptr.- Creational:
main.cpp: קרא קלט יחיד: שם של תבנית עיצוב.צור
PatternClassifierוהשתמש בו כדי לסווג את תבנית הקלט. אם התבנית מזוהה, הדפס:[PatternName] is a [CategoryName] pattern Purpose: [CategoryPurpose]אם התבנית אינה מזוהה, הדפס:
Unknown pattern: [PatternName]
לדוגמה, עבור הקלט Singleton:
Singleton is a Creational pattern
Purpose: Object creation mechanismsעבור הקלט Observer:
Observer is a Behavioral pattern
Purpose: Object interaction and responsibilityעבור הקלט Proxy:
Unknown pattern: Proxyהאתגר הזה מחזק את ההיכרות עם שלוש הקטגוריות של תבניות עיצוב, ובמקביל מאפשר לתרגל ירושה, פולימורפיזם ומצביעים חכמים — מושגים שכבר שלטת בהם. המבנה הכולל כמה קבצים משקף את האופן שבו פרויקטים אמיתיים מארגנים מחלקות קשורות.
נסו בעצמכם
#include <iostream>
#include <string>
#include "PatternClassifier.h"
int main() {
// קרא את שם התבנית
std::string patternName;
std::cin >> patternName;
// TODO: צור מופע של PatternClassifier
// TODO: השתמש במסווג כדי לסווג את תבנית הקלט
// TODO: אם התבנית מזוהה, הדפס:
// "[PatternName] is a [CategoryName] pattern"
// "Purpose: [CategoryPurpose]"
// TODO: אם התבנית אינה מזוהה (nullptr), הדפס:
// "Unknown pattern: [PatternName]"
return 0;
}
השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.
כל השיעורים ביחידה תכנות מונחה עצמים
1יסודות OOP
קבצים חיצונייםבנייה וקומפילציה של C++קובצי Header וקובצי מקורמרחבי שמות והיקףמבוא ל-OOP ב-C++מחלקות לעומת אובייקטיםמצביע thisמתודות (פונקציות איבר)תכונות (חברי נתונים)יסודות הבנאים וההורסיםסיכום – מחשבון פשוט4מאפייני מחלקה
חברי מופע לעומת חברים סטטייםגטרים וסטריםפונקציות איבר קבועותמילת המפתח mutableמתודות ומשתנים סטטייםפונקציות ומחלקות ידידותסיכום – מנהל חשבונות בנק7ירושה
ירושה בסיסיתרמות גישה בירושהסדר הקריאות לבנאי ולמפרקדריסת מתודותפונקציות וירטואליות ו־VTableירושה מרובהירושה וירטואליתסיכום – היררכיית עובדים10סקירה כללית של STL
סקירה כללית והפילוסופיה של STLקונטיינרים של STLאיטרטוריםאלגוריתמים של STLפונקטורים וביטויי למבדהסיכום – תדירות מילים13תבניות עיצוב חלק 1
מבוא לתבניות עיצובתבנית SingletonFactory ו־Abstract Factoryתבנית Builderתבנית Observerתבנית Strategy2ניהול זיכרון
זיכרון Stack לעומת Heapמצביעים והפניותזיכרון דינמי (new/delete)מצביעים חכמים ב-C++RAII ב-C++סיכום – מנהל מערכים דינמיים5כימוס
מצייני גישה ב-C++מצייני גישה לעומקהסתרת מידעמבנה לעומת מחלקהמחלקות מקוננות ופנימיותסיכום – מערכת רשומות תלמידים8רב־צורתיות
רב־צורתיות בזמן קומפילציה לעומת בזמן ריצההעמסת פונקציותפונקציות וירטואליות — מבט נוסףפונקציות וירטואליות טהורותמחלקות מופשטותתכנון ממשקים ב־C++המרה דינמית ו־RTTIסיכום — מחשבון צורות3בנאים והורסים
בנאי ברירת מחדלבנאי עם פרמטריםבנאי העתקהבנאי העברהרשימות אתחול בבנאיםבנאים מאציליםמעמיקים בנושא הורסיםכלל השלושה / החמישה / האפססיכום – מחלקת String6העמסת אופרטורים
מבוא להעמסת אופרטוריםהעמסת אופרטורים אריתמטייםהעמסת אופרטורי השוואהאופרטורי זרםהעמסת אופרטור השמההעמסת האופרטורים [] ו־()אופרטורים להמרת טיפוסיםסיכום – מחלקת Matrix9תבניות
תבניות פונקציהתבניות מחלקההתמחות תבניותתבניות ארגומנטים משתנותיסודות SFINAE ותכונות טיפוסיםסיכום – מכל גנריתרגלו בעצמכם: קומפיילר C++ אונליין