ראשי > strategy pattern > חלק שלישי
The Strategy

כמה נקודות בקשר למימוש:
למעלה
קוד לדוגמה:
ניתן דוגמה של קוד עבור הדוגמה שנתנו בסעיף המוטיבציה. מחלקת ה Composition מטפלת באוסף של מופעי Component , אשר מייצגים טקסט ואלמנטים גרפיים במסמך. Composition מארגן אובייקטים מסוג Component לשורות תוך שימוש במופע של subclass של Compositor שמרכז בתוכו אסטרטגיה לשבירת שורות. לכל component יש size, stretchability, ו shrinkablility. ה stretchability מגדירה עד כמה component יכול לגדול מעבר לגודל שלו, ו shrinkability מגדירה עד כמה ניתן לכווץ אותו. ה Composition מעביר את הערכים הללו ל compositor אשר נעזר בהם על מנת לקבוע את המיקומים הטובים ביותר לשבירת שורות.

class Composition {
public:
     Composition(Compositor*);
     void Repair();
private:
     Compositor* _compositor;
     Component* _components; // the list of components
     int _componentCount; // the number of components
     int _lineWidth;   // the Composition's line width
     int* _lineBreaks; // the position of linebreaks
                       // in components
     int _lineCount;   // the number of lines
};

כאשר נזדקק לסידור חדש, ה composition יבקש מה compositor שלו לקבוע היכן למקם את שבירת השורות. ה composition מעביר ל compositor שלושה מערכים שמגדירים size, stretchability, ו shrinkability של כל הcomponent ים. הוא גם מעביר את מספר ה component ים, רוחב שורה, ומערך שה compositor ימלא במיקומים של כל שבירות השורות. ה compositor מצדו מחזיר את מספר השבירות שמחושב על ידיו.
הממשק של Compositor מאפשר ל composition להעביר לו את כל האינפורמציה שהוא זקוק לה. זו דוגמה לגישה של "לקחת את ה data אל ה Strategy":

class Compositor {
public:
     virtual int Compose (
     Coord natural[], Coord stretch[], Coord shrink[],
     int componentCount, int lineWidth, int breaks[]
     ) = 0;
protected:
     Compositor();
};

שימו לב ש Compositor הוא
abstract class. ה concrete subclasses שלו מגדירים אסטרטגיות ספציפיות לשבירת שורות.
ה composition קורא ל compositor שלו בפעולת ה Repair() . תחילה היא מאתחלת מערכים עם ה size, ה stretchability, ו ה shrinkability של כל component (פרטים אלה נשמיט למען הקיצור וכדי שלא תאבדו ריכוז...). לאחר מכן היא קוראת ל compositor כדי לקבוע את נקודות שבירת השורות, ולבסוף מסדרת את ה component ים בהתאם לשבירות (גם פרט זה הושמט כאן למען הקיצור, זה רק למענכם...):

void Composition::Repair() {
     Coord* natural;
     Coord* stretchability;
     Coord* shrinkability;
     int componentCount;
     int* breaks;

     // prepare the arrays with the desired
     // component sizes
     // ...

     // determine where the breaks are:
     int breakCount;
     breakCount = _compositor->Compose(
      natural, stretchability, shrinkability,
      componentCount, _lineWidth, breaks
     );

     // lay out components according to breaks
     // ...
}

הבה ונסתכל ב subclass ים של Compositor. ה SimpleCompositor בוחן component ים שורה אחר שורה וקובע היכן השבירות ימוקמו:

class SimpleCompositor : public Compositor {
public:
     SimpleCompositor();

     virtual int Compose(
     Coord natural[], Coord stretch[], Coord shrink[],
     int componentCount, int lineWidth, int breaks[]
     );
     // ...
};

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

class TeXCompositor : public Compositor {
public:
     TeXCompositor();

     virtual int Compose(
     Coord natural[], Coord stretch[], Coord shrink[],
     int componentCount, int lineWidth, int breaks[]
     );
     // ...
};

ArrayCompositor שובר את ה component ים לשורות עם רווחים קבועים בין ה component ים.

class ArrayCompositor : public Compositor {
public:
     ArrayCompositor(int interval);

     virtual int Compose(
     Coord natural[], Coord stretch[], Coord shrink[],
     int componentCount, int lineWidth, int breaks[]
     );
     // ...
};

שימו לב שלא כל ה compositor ים משתמשים בכל ה data שנשלח אליהם: SimpleCompositor מתעלם מה stretchability, ולוקח בחשבון רק את הרוחב הטבעי שלהם. TeXCompositor משתמש בכל המידע שנשלח אליו, ו ArrayCompositor מתעלם מהכל. כדי ליצור Composition נעביר לו את ה Compositor שנרצה שישתמש בו:

Composition* quick = new Composition(
     new SimpleCompositor
     );
Composition* slick = new Composition(new TeXCompositor);
Composition* iconic = new Compostion(
     new ArrayCompositor(100)
     );

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

למעלה







 
מה בעמוד:
 
מימוש
קוד לדוגמה