223. Template method pattern

הכרנו קצת מהן פונקציות וירטואליות.

יישום מאוד שימושי וחזק של פונקציות וירטואליות הוא כתיבת Template methods.

Template method זו בעצם מתודה רגילה, הקוראת למתודות אחרות של האובייקט שלנו.

הTwist פה הוא שחלק מהמתודות אותן הTemplate method מפעילה, הן מתודות וירטואליות.

לדוגמה, נניח שיש לנו מחלקה כזאת:

1
2
3
4
5
6
7
8
9
10
11
12
public abstract class DrinkMachine
{
protected abstract int GetProductAmount(string productId);
protected abstract void SetProductAmount(string productId, int amount);
protected abstract int GetProductPrice(string productId);
protected abstract bool CanCharge(int price);
protected abstract void Charge(int price);
protected abstract int ReturnChange();
}

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public void BuyDrink(string productId)
{
int productsAvailable = GetProductAmount(productId);
if (productsAvailable == 0)
{
throw new ArgumentException("productId",
"No products of type " + productId + " are available");
}
int productPrice = GetProductPrice(productId);
if (!CanCharge(productPrice))
{
throw new Exception("Not enough money available. Excepted at least " + productPrice);
}
else
{
Charge(productPrice);
SetProductAmount(productId, productsAvailable - 1);
ReturnChange();
}
}

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

כעת מי שירש מהמחלקה שלנו, יקבל אוטומטית מימוש לפונקציה BuyDrink.

הדבר הזה מאוד חזק.

הוא מאפשר מספר דברים טובים:

  1. מניעת שכפול קוד – במקום שכל אחד יממש בעצמו את הפונקציה הזאת, היא ממומשת פעם אחת בBase.
  2. שינוי התנהגות של המחלקה ע"י ירושה ודריסה.
  3. נקודות כניסה מוגבלות – במקום שהTemplate Method יהיה וירטואלי וכל אחד ידרוס אותו, אנחנו יכולים להגביל אותו, ולאפשר לדרוס רק את הפונקציות שהוא משתמש בהן.

המשך טיוטת יום וירטואלי טוב.

שתף