תבנית המצב
חלק מהיחידה תכנות מונחה עצמים במסלול ה-C# של Coddy. שיעור 60 מתוך 70.
תבנית State היא תבנית התנהגותית שמאפשרת לאובייקט לשנות את ההתנהגות שלו כאשר המצב הפנימי שלו משתנה. במקום להשתמש במשפטי תנאי מורכבים כדי לטפל במצבים שונים, עוטפים כל מצב במחלקה משלו ומאצילים את ההתנהגות לאובייקט המצב הנוכחי.
התבנית מורכבת משלושה רכיבים: ממשק מצב המגדיר התנהגות ספציפית למצב, מחלקות מצב קונקרטיות המממשות התנהגות זו, ומחלקת הקשר השומרת הפניה למצב הנוכחי:
public interface IDocumentState
{
void Publish(Document doc);
}
public class DraftState : IDocumentState
{
public void Publish(Document doc)
{
Console.WriteLine("Moving to moderation");
doc.SetState(new ModerationState());
}
}
public class ModerationState : IDocumentState
{
public void Publish(Document doc)
{
Console.WriteLine("Publishing document");
doc.SetState(new PublishedState());
}
}
public class PublishedState : IDocumentState
{
public void Publish(Document doc)
{
Console.WriteLine("Already published");
}
}ההקשר מחזיק את המצב הנוכחי ומאציל לו פעולות. אובייקטי מצב יכולים להפעיל מעברים באמצעות קריאה ל-SetState() בהקשר:
public class Document
{
private IDocumentState _state = new DraftState();
public void SetState(IDocumentState state) => _state = state;
public void Publish() => _state.Publish(this);
}
var doc = new Document();
doc.Publish(); // מעבר לבדיקה
doc.Publish(); // פרסום המסמך
doc.Publish(); // כבר פורסםתבנית State מבטלת הצהרות if-else או switch מסועפות שבודקות את המצב הנוכחי. כל מחלקת מצב מטפלת רק בהתנהגות שלה, וכך קל יותר לתחזק את הקוד ולהרחיב אותו באמצעות מצבים חדשים.
אתגר
קלבואו נבנה מערכת רמזורים באמצעות תבנית State. הרמזור עובר בין מצבים שונים (אדום, צהוב, ירוק), וכל מצב קובע מה קורה כשהרמזור מתחלף. במקום להשתמש בתנאים מורכבים, תעטפו כל מצב של הרמזור במחלקה משלו.
תארגנו את הקוד שלכם בשלושה קבצים:
TrafficLightState.cs: הגדירו ממשקITrafficLightStateבמרחב השמותTrafficעם מתודהChange(TrafficLight light). לאחר מכן צרו שלוש מחלקות מצב קונקרטיות:RedState- כשקוראים ל־Change, היא מדפיסהRed - Stop! Changing to Green...ומעבירה את הרמזור ל־GreenStateGreenState- מדפיסהGreen - Go! Changing to Yellow...ומעבירה למצבYellowStateYellowState- מדפיסהYellow - Caution! Changing to Red...ומעבירה למצבRedState
TrafficLight.cs: צרו מחלקהTrafficLightבאותו מרחב שמות. זו מחלקת ההקשר שלכם, שמחזיקה את המצב הנוכחי. כברירת מחדל, היא צריכה להתחיל במצבRedStateולהכיל:- מתודה
SetState(ITrafficLightState state)שאובייקטי מצב משתמשים בה כדי להפעיל מעברים - מתודה
Change()שמעבירה את הקריאה למתודתChangeשל המצב הנוכחי
- מתודה
Program.cs: חברו את כל החלקים באמצעות יצירת אובייקטTrafficLightומעבר בין מצבים בהתאם לקלט.
יתקבל קלט אחד:
- מספר הפעמים לשינוי מצב הרמזור (מספר שלם)
צרו אובייקט TrafficLight (שמתחיל באור אדום) וקראו ל־Change() מספר הפעמים שצוין.
לדוגמה, אם הקלט הוא 3, הפלט יהיה:
Red - Stop! Changing to Green...
Green - Go! Changing to Yellow...
Yellow - Caution! Changing to Red...אם הקלט הוא 5, הרמזור יחזור לתחילת המחזור:
Red - Stop! Changing to Green...
Green - Go! Changing to Yellow...
Yellow - Caution! Changing to Red...
Red - Stop! Changing to Green...
Green - Go! Changing to Yellow...שימו לב שמחלקת TrafficLight אינה מכילה לוגיקה לגבי משמעותו של כל צבע או מהו המצב הבא - כל הידע הזה נמצא במחלקות המצב הנפרדות. כל מצב אחראי להתנהגות שלו ולהפעלת המעבר למצב הבא!
נסו בעצמכם
using System;
using Traffic;
class Program
{
public static void Main(String[] args)
{
// קרא את מספר הפעמים שיש לשנות את מצב הרמזור
int n = Convert.ToInt32(Console.ReadLine());
// TODO: צור מופע של TrafficLight (מתחיל ב-RedState כברירת מחדל)
// TODO: קרא למתודה Change() n פעמים באמצעות לולאה
}
}
השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.
כל השיעורים ביחידה תכנות מונחה עצמים
1יסודות התכנות מונחה העצמים
קבצים חיצונייםמרחבי שמות והנחיותמבוא למחלקות ולאובייקטיםמילת המפתח 'this'מתודות ופרמטריםשדות לעומת מאפייניםבנאיםאתחול אובייקטיםסיכום – מחשבון פשוט4ירושה
תחביר ירושה בסיסית (:)מילת המפתח 'base'מילות המפתח Virtual ו-Overrideמחלקות Sealedמחלקת הבסיס 'object'סיכום – היררכיית עובדים7תכונות מתקדמות
העמסת אופרטוריםאינדקסרים (this[])דריסת ToString()מתודות הרחבהסיכום – רשימה מותאמת אישית2מאפיינים וחברים סטטיים
מאפיינים במימוש אוטומטימאפיינים לקריאה בלבד ולכתיבה בלבדשדות ומתודות סטטייםמחלקות סטטיותחברים עם גוף ביטוי5פולימורפיזם וממשקים
פולימורפיזם בזמן קומפילציה לעומת בזמן ריצהממשק לעומת מחלקה מופשטתממשקים מרוביםממשקים מפורשיםהמרה כלפי מעלה והמרה כלפי מטהחזרה: מחשבון צורות8מושגים מתקדמים בתכנות מונחה עצמים
קומפוזיציה במקום ירושהGenerics (מחלקות ומתודות)נציגים ואירועיםמאפיינים ורפלקציהIDisposable והצהרת usingיסודות הזרקת תלויותתרגלו בעצמכם: קומפיילר C# אונליין