Menu
Coddy logo textTech

תבנית המתאם

חלק מהיחידה תכנות מונחה עצמים במסלול ה-PHP של Coddy. שיעור 76 מתוך 91.

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

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

<?php
// הממשק שהיישום שלך מצפה לו
interface PaymentProcessor {
    public function pay(float $amount): string;
}

// ספריית צד שלישי עם ממשק שונה
class StripeAPI {
    public function createCharge(int $cents, string $currency): string {
        return "Charged {$cents} {$currency} via Stripe";
    }
}

המתאם מממש את הממשק המצופה שלך, ובתוך כך משתמש במחלקה של צד שלישי:

<?php
class StripeAdapter implements PaymentProcessor {
    public function __construct(private StripeAPI $stripe) {}
    
    public function pay(float $amount): string {
        $cents = (int)($amount * 100);
        return $this->stripe->createCharge($cents, 'USD');
    }
}

$stripe = new StripeAPI();
$processor = new StripeAdapter($stripe);
echo $processor->pay(29.99);

פלט:

Charged 2999 USD via Stripe

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

challenge icon

אתגר

קל

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

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

  • TemperatureSensor.php: הגדירו ממשק TemperatureSensor שאפליקציית מזג האוויר שלכם מצפה לו. צריכה להיות בו מתודה getTemperature(): float שמחזירה את הטמפרטורה בצלזיוס.
  • LegacySensor.php: צרו מחלקה LegacySensor שמדמה את החומרה הישנה. למחלקה הזאת יש ממשק שונה מזה שהאפליקציה שלכם צריכה:
    • היא מקבלת קריאת טמפרטורה בפרנהייט בבנאי שלה (השתמשו בקידום מאפיינים בבנאי)
    • יש לה מתודה readFahrenheit(): float שמחזירה את ערך הפרנהייט שנשמר
  • LegacySensorAdapter.php: כללו את הממשק TemperatureSensor ואת המחלקה LegacySensor. צרו מחלקה LegacySensorAdapter שמממשת את TemperatureSensor ועוטפת את LegacySensor. המתאם שלכם צריך:
    • לקבל LegacySensor בבנאי שלו
    • לממש את getTemperature() באמצעות קריאת ערך הפרנהייט מהחיישן הישן והמרתו לצלזיוס לפי הנוסחה: (fahrenheit - 32) * 5 / 9
  • main.php: כללו את הקובץ LegacySensorAdapter. תקבלו קלט אחד: טמפרטורה בפרנהייט.

    צרו LegacySensor עם טמפרטורת הקלט, ואז עטפו אותו ב-LegacySensorAdapter. קראו ל-getTemperature() במתאם והדפיסו את התוצאה כשהיא מעוגלת לשתי ספרות אחרי הנקודה העשרונית.

    פורמט הפלט צריך להיות: Temperature: [celsius]C

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

נסו בעצמכם

<?php
require_once 'LegacySensorAdapter.php';

// קרא את הקלט
$fahrenheit = floatval(trim(fgets(STDIN)));

// TODO: צור LegacySensor עם טמפרטורת הקלט
// TODO: עטוף אותו ב-LegacySensorAdapter
// TODO: קרא ל-getTemperature() על המתאם
// TODO: הדפס את התוצאה מעוגלת לשתי ספרות אחרי הנקודה העשרונית
// תבנית הפלט: Temperature: [celsius]C

?>
quiz iconבחנו את עצמכם

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

כל השיעורים ביחידה תכנות מונחה עצמים

תרגלו בעצמכם: קומפיילר PHP אונליין