תבנית עיצוב היא תבנית שפותרת בעיה שחוזרת על עצמה בעיצוב תוכנה.

דפוס המצב הוא דפוס התנהגותי המאפשר לאובייקט לשנות את התנהגותו כאשר מצבו הפנימי משתנה.

כאן תלמדו כיצד להשתמש בדפוס המצב ב-TypeScript.

מהי דפוס המדינה?

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

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

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

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

אפליקציה מבוססת מדינה לדוגמה

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

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

instagram viewer

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

מִמְשָׁקממשק מאמר{
גובה הצליל(): בָּטֵל;
טְיוּטָה(): בָּטֵל;
לַעֲרוֹך(): בָּטֵל;
לְפַרְסֵם(): בָּטֵל;
}

ממשק זה יכלול את כל המצבים האפשריים של היישום.

לאחר מכן, צור יישום המיישם את כל שיטות הממשק:

// יישום
מעמדמאמרמיישםממשק מאמר{
בַּנַאִי() {
זֶה.showCurrentState();
}

פְּרָטִיshowCurrentState(): בָּטֵל{
//...
}

פּוּמְבֵּיגובה הצליל(): בָּטֵל{
//...
}

פּוּמְבֵּיטְיוּטָה(): בָּטֵל{
//...
}

פּוּמְבֵּילַעֲרוֹך(): בָּטֵל{
//...
}

פּוּמְבֵּילְפַרְסֵם(): בָּטֵל{
//...
}
}

הפרטית showCurrentState שיטה היא שיטת שירות. מדריך זה משתמש בו כדי להראות מה קורה בכל מדינה. זה לא חלק נדרש מדפוס המדינה.

טיפול במעברי מדינה

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

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

לדוגמה:

תַקצִירמעמדArticleStateמיישםממשק מאמר{
pitch(): ArticleState {
לזרוקחָדָשׁשְׁגִיאָה("פעולה לא חוקית: לא ניתן לבצע משימה ב מצב נוכחי");
}

draft(): ArticleState {
לזרוקחָדָשׁשְׁגִיאָה("פעולה לא חוקית: לא ניתן לבצע משימה ב מצב נוכחי");
}

עריכה(): ArticleState {
לזרוקחָדָשׁשְׁגִיאָה("פעולה לא חוקית: לא ניתן לבצע משימה ב מצב נוכחי");
}

publish(): ArticleState {
לזרוקחָדָשׁשְׁגִיאָה("פעולה לא חוקית: לא ניתן לבצע משימה ב מצב נוכחי");
}
}

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

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

לדוגמה:

מעמדPendingDraftStateמשתרעArticleState{
pitch(): ArticleState {
לַחֲזוֹרחָדָשׁ DraftState();
}
}

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

לאחר מכן, תעקוף את שאר השיטות כך:

מעמדDraftStateמשתרעArticleState{
draft(): ArticleState {
לַחֲזוֹרחָדָשׁ EditingState();
}
}

קוד זה עוקף את טְיוּטָה שיטה ומחזירה מופע של ה מצב עריכה.

מעמדמצב עריכהמשתרעArticleState{
עריכה(): ArticleState {
לַחֲזוֹרחָדָשׁ PublishedState();
}
}

בלוק הקוד שלמעלה עוקף את לַעֲרוֹך שיטה ומחזירה מופע של PublishedState.

מעמדPublishedStateמשתרעArticleState{
publish(): ArticleState {
לַחֲזוֹרחָדָשׁ PendingDraftState();
}
}

בלוק הקוד שלמעלה עוקף את לְפַרְסֵם שיטה ומחזירה את האפליקציה למצב סרק שלה, PendingDraftState.

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

פְּרָטִי מדינה: ArticleState = חָדָשׁ PendingDraftState();

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

פְּרָטִיshowCurrentState(): בָּטֵל{
לְנַחֵם.עֵץ(זֶה.מדינה);
}

ה showCurrentState השיטה מתעדת את המצב הנוכחי של היישום למסוף.

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

לדוגמה, עדכן את היישומים שלך גובה הצליל שיטה לבלוק הקוד למטה:

פּוּמְבֵּיגובה הצליל(): בָּטֵל{
זֶה.state = זֶה.state.pitch();
זֶה.showCurrentState();
}

בבלוק הקוד למעלה, ה- גובה הצליל השיטה משנה את המצב מהמצב הנוכחי למצב הגובה.

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

עדכן את שיטות היישום שלך לקוביות הקוד שלהלן:

ה טְיוּטָה שיטה:

פּוּמְבֵּיטְיוּטָה(): בָּטֵל{
זֶה.state = זֶה.state.draft();
זֶה.showCurrentState();
}

ה לַעֲרוֹך שיטה:

פּוּמְבֵּילַעֲרוֹך(): בָּטֵל{
זֶה.state = זֶה.state.edit();
זֶה.showCurrentState();
}

וה לְפַרְסֵם שיטה:

פּוּמְבֵּילְפַרְסֵם(): בָּטֵל{
זֶה.state = זֶה.state.publish();
זֶה.showCurrentState();
}

שימוש ביישום המוגמר

מחלקת היישום המוגמרת שלך צריכה להיות דומה לגוש הקוד שלהלן:

// יישום
מעמדמאמרמיישםממשק מאמר{
פְּרָטִי מדינה: ArticleState = חָדָשׁ PendingDraftState();

בַּנַאִי() {
זֶה.showCurrentState();
}

פְּרָטִיshowCurrentState(): בָּטֵל{
לְנַחֵם.עֵץ(זֶה.מדינה);
}

פּוּמְבֵּיגובה הצליל(): בָּטֵל{
זֶה.state = זֶה.state.pitch();
זֶה.showCurrentState();
}

פּוּמְבֵּיטְיוּטָה(): בָּטֵל{
זֶה.state = זֶה.state.draft();
זֶה.showCurrentState();
}

פּוּמְבֵּילַעֲרוֹך(): בָּטֵל{
זֶה.state = זֶה.state.edit();
זֶה.showCurrentState();
}

פּוּמְבֵּילְפַרְסֵם(): בָּטֵל{
זֶה.state = זֶה.state.publish();
זֶה.showCurrentState();
}
}

אתה יכול לבדוק את מעברי המצב על ידי קריאה לשיטות ברצף הנכון. לדוגמה:

const מסמכים = חָדָשׁ מאמר(); // PendingDraftState: {}

docs.pitch(); // DraftState: {}
docs.draft(); // מצב עריכה: {}
docs.edit(); // פורסם מצב: {}
docs.publish(); // PendingDraftState: {}

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

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

const מסמכים = חָדָשׁ מאמר(); // PendingDraftState: {}
docs.pitch() // DraftState: {}
docs.edit() // פעולה לא חוקית: לא ניתן לבצע משימה במצב הנוכחי

עליך להשתמש בדפוס זה רק כאשר:

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

יתרונות ופשרות של דפוס המדינה

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