Command חלק א

21 בSeptember 2012

אין תגובות

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

לדוגמא בWPF MVVM , 

 

הרעיון : לעטוף מימוש של פעולה בקלאס,

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

Interface pattern)) ואין שום קשר בין התבניות )

מבנה התבנית:
























Command הוא קלאס (המבנה שלו מגיע
לרוב דרך אינטרפייס או ירושה) עם פונקציה מרכזית
execute שמבצעת את הפעולה המיועדת
(הפעלת הפונקציה שנעטפה בתוך ה
command) , כמובן במבנים מסוימים
כמו
ICommand Interface של #C  ישנה גם פונקציה canExecute וevent
 תואם
לעדכן אם ישנו שינוי במצב, אבל זה כבר תוספות על המבנה הבסיסי.

 

בנוסף , בתבנית שני שחקנים מרכזיים נוספים  ,

Invoker זה שמפעיל את הפקודה
(הפעולה הטכנית כמו
click)

Client בד”כ האפליקציה,
יוצר מופע של ה
command וקובע למי הפקודה מתחברת.

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

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

וזה מאפשר לנו :

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

ב. שמירת סטייט (מצב), בתנאי שכל הפעולות נעשות דרך command מאחר שפעולה שבוצעה דרך command היא לא סתם פונקציה אלא קלאס וניתן לשמור
אותם במחסנית ולהעיף את האחרון לצרכי
Undo שזה השימוש הנפוץ ביותר
כנראה ל
Command באפליקציות.

ג. סוג של אינקפסולציה, – can
executed
פעולה חוקית או לא.. לדוגמא אין paste לפני cut

ד.  למפתחי   xaml את האופציה להשתמש ב MVVM , לרוב ישנו command  מוכן
בכל תשתית
WPF שמכבדת את עצמה.

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

 

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

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

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

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

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

ובנימה אישית : מה היה עושה מתכנת בלי היכולת של copy paste  ?
משבר אפוקליפטי…..

דוגמא בסיסית:

א.    
נגדיר
חוזה ל
command  שלנו

   public interface ICommand

    {

        void execute();

     }

                                                                                                                                 

                                                                          

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

public class RunCommand : ICommand

    {

        public void execute()

        {

            Console.WriteLine(“runing…..”);

        }

    }

 

    public class StopCommand : ICommand

    {

        public void execute()

        {

            Console.WriteLine(“stop runing……….”);

        }

                                                                                                                                                               
                                                                     {

ג.      
נגדיר
קלאס שמשתמש ב
commands  האלה  

הוא יודע
לקבל
command  ולהריץ אותם , לפי מה שהם מוגדרים לעשות..

 

public class MarathonRunner

    {

        public void invoke(ICommand usercommand)

        {

            Console.WriteLine(“activate
command >>>”
);

            usercommand.execute();

        }

   
                                                                                          {                                                                      

ד.     
וזהו ..
רק להריץ כדי ל”הרגיש” את זה.

     class Program

    {

        static void Main(string[] args)

        {

 

            MarathonRunner olimpicRunner = new MarathonRunner ();

            Stopcommand stopCmd = new Stopcommand();

            RunCommand runkCmd = new RunCommand ();

 

            olimpicWalker.invoke(runkCmd);

            olimpicWalker.invoke(stopCmd);

        }

     }

      

                                                                                                                                                                                           

מה שהדגמנו פה זה קלאס שמייצג רץ מרתון.

לרץ אמורות להיות 2 פונקציות פשוטות , רוץ , עצור,

כיון שאנחנו במוד של command הגדרנו אחד כזה לכל
פונקציה(קלאס לכל דבר ועניין)  ,

אותו קלאס הוא מימוש של חוזה Icommand אשר על כן הוא עושה משהו
עם הפונקציה

היחידה שיש לחוזה(execute). 

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

עם command מתאים וזהו.

בפוסט הבא  ניקח את התבנית צעד אחד קדימה ונבנה תבנית של undo / redo.

 

הוסף תגובה
facebook linkedin twitter email

Leave a Reply

Your email address will not be published. Required fields are marked *