Menu
Coddy logo textTech

תבנית המתאם

חלק מהיחידה תכנות מונחה עצמים במסלול ה-Python של Coddy. שיעור 50 מתוך 64.

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

הנה שתי מערכות עם ממשקים שאינם תואמים:

class OldPrinter:
    def old_print(self, text):
        return f"OLD: {text}"

class NewPrinter:
    def print(self, text):
        return f"NEW: {text}"

המדפסת הישנה משתמשת ב־old_print(), בעוד שהחדשה משתמשת ב־print().

צרו מתאם שיאפשר למדפסת הישנה לעבוד עם הממשק החדש:

class PrinterAdapter:
    def __init__(self, old_printer):
        self.old_printer = old_printer
    
    def print(self, text):
        # התאם את הממשק הישן לממשק החדש
        return self.old_printer.old_print(text)

המתאם עוטף את המדפסת הישנה ומספק את הממשק המצופה.

השתמשו בשתי המדפסות עם אותו קוד לקוח:

def print_document(printer, text):
    return printer.print(text)  # מצפה למתודה print()

# השתמש במדפסת החדשה ישירות
new_printer = NewPrinter()
print(print_document(new_printer, "Hello"))

# השתמש במדפסת הישנה דרך המתאם
old_printer = OldPrinter()
adapter = PrinterAdapter(old_printer)
print(print_document(adapter, "Hello"))

צרו דוגמה נוספת עם נגני מדיה:

class Mp3Player:
    def play_mp3(self, filename):
        return f"Playing MP3: {filename}"

class Mp4Player:
    def play_mp4(self, filename):
        return f"Playing MP4: {filename}"

class MediaAdapter:
    def __init__(self, player, audio_type):
        self.player = player
        self.audio_type = audio_type
    
    def play(self, filename):
        if self.audio_type == "mp3":
            return self.player.play_mp3(filename)
        elif self.audio_type == "mp4":
            return self.player.play_mp4(filename)
class AudioPlayer:
    def play(self, audio_type, filename):
        if audio_type == "mp3":
            return Mp3Player().play_mp3(filename)
        else:
            adapter = MediaAdapter(Mp4Player(), audio_type)
            return adapter.play(filename)

player = AudioPlayer()
print(player.play("mp3", "song.mp3"))
print(player.play("mp4", "video.mp4"))

פלט:

NEW: Hello
OLD: Hello
Playing MP3: song.mp3
Playing MP4: video.mp4

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

challenge icon

אתגר

בינוני

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

 

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

עליכם:

  1. להבין את הממשקים המודרניים שהוגדרו ב־interfaces.py (אי אפשר לשנות את הקובץ הזה)
  2. לבחון את הרכיבים הישנים שב־legacy_system.py (אי אפשר לשנות את הקובץ הזה)
  3. לממש מחלקות מתאם ב־adapters.py כדי להפוך את הרכיבים הישנים לתואמים לממשקים המודרניים
  4. ליצור מערכת מודרנית ב־modern_system.py שמשתמשת בממשקים האלה

נסו בעצמכם

# ייבא את כל המחלקות הדרושות
from adapters import LegacyDataAnalyzerAdapter, LegacyChartGeneratorAdapter
from modern_system import AnalyticsSystem

# מנגנון מקיף לטיפול במקרי בדיקה
test_case = input()

if test_case == "basic_adapter_test":
    # בדוק את הפונקציונליות הבסיסית של המתאם
    processor = LegacyDataAnalyzerAdapter()
    data = [1, 2, 3, 4, 5]
    processor.process_data(data)
    results = processor.get_results()
    print(f"Results: {results}")

elif test_case == "visualizer_adapter_test":
    # בדוק את מתאם ההמחשה
    visualizer = LegacyChartGeneratorAdapter("bar")
    data = [10, 20, 30, 40, 50]
    success = visualizer.visualize(data)
    if success:
        export_success = visualizer.export_visualization("test_chart.png")
        print(f"Visualization exported: {export_success}")

elif test_case == "analytics_system_test":
    # בדוק את מערכת הניתוח המלאה
    processor = LegacyDataAnalyzerAdapter()
    visualizer = LegacyChartGeneratorAdapter("line")
    system = AnalyticsSystem(processor, visualizer)
    
    data = [15, 25, 35, 45, 55]
    result = system.analyze_and_visualize(data, "analytics_output.png")
    print(f"System result: {result}")

elif test_case == "validation_error_test":
    # בדוק שגיאות אימות
    processor = LegacyDataAnalyzerAdapter()
    try:
        processor.process_data("invalid_data")
        print("Validation failed - should have raised ValueError")
    except ValueError as e:
        print(f"Validation error caught: {e}")

elif test_case == "empty_data_test":
    # בדוק עם נתונים ריקים
    processor = LegacyDataAnalyzerAdapter()
    try:
        processor.process_data([])
        results = processor.get_results()
        print(f"Empty data results: {results}")
    except Exception as e:
        print(f"Empty data error: {e}")

elif test_case == "chart_types_test":
    # בדוק סוגים שונים של תרשימים
    chart_types = ["bar", "line", "pie"]
    data = [5, 15, 25, 35]
    
    for chart_type in chart_types:
        visualizer = LegacyChartGeneratorAdapter(chart_type)
        success = visualizer.visualize(data)
        print(f"{chart_type} chart created: {success}")

elif test_case == "file_extension_test":
    # בדוק את הטיפול בסיומות קבצים
    visualizer = LegacyChartGeneratorAdapter()
    data = [1, 2, 3, 4]
    visualizer.visualize(data)
    
    # בדוק פורמטים שונים של שמות קבצים
    filenames = ["test", "test.jpg", "test.pdf", "test.png"]
    for filename in filenames:
        success = visualizer.export_visualization(filename)
        print(f"Export '{filename}': {success}")

elif test_case == "summary_test":
    # בדוק את סיכום הניתוח
    processor = LegacyDataAnalyzerAdapter()
    visualizer = LegacyChartGeneratorAdapter()
    system = AnalyticsSystem(processor, visualizer)
    
    data = [10, 20, 30, 40, 50, 60]
    system.analyze_and_visualize(data)
    summary = system.get_analysis_summary()
    print("Analysis Summary:")
    print(summary)

elif test_case == "mixed_data_test":
    # בדוק עם נתונים מספריים מעורבים
    processor = LegacyDataAnalyzerAdapter()
    data = [1.5, 2, 3.7, 4, 5.2]
    processor.process_data(data)
    results = processor.get_results()
    print(f"Mixed data results: {results}")

elif test_case == "invalid_numeric_test":
    # בדוק עם נתונים מספריים לא תקינים
    processor = LegacyDataAnalyzerAdapter()
    try:
        processor.process_data([1, 2, "three", 4, 5])
        print("Validation failed - should have raised ValueError")
    except ValueError as e:
        print(f"Invalid numeric data error: {e}")

elif test_case == "no_results_summary_test":
    # בדוק סיכום ללא תוצאות
    processor = LegacyDataAnalyzerAdapter()
    visualizer = LegacyChartGeneratorAdapter()
    system = AnalyticsSystem(processor, visualizer)
    
    summary = system.get_analysis_summary()
    print(f"No results summary: {summary}")

elif test_case == "large_dataset_test":
    # בדוק עם מערך נתונים גדול יותר
    processor = LegacyDataAnalyzerAdapter()
    data = list(range(1, 101))  # 1 עד 100
    processor.process_data(data)
    results = processor.get_results()
    print(f"Large dataset - Mean: {results.get('mean', 'N/A'):.2f}")
    print(f"Large dataset - Min: {results.get('min', 'N/A')}")
    print(f"Large dataset - Max: {results.get('max', 'N/A')}")

elif test_case == "complete_workflow_test":
    # בדוק תהליך עבודה מלא עם מספר פעולות
    processor = LegacyDataAnalyzerAdapter()
    bar_visualizer = LegacyChartGeneratorAdapter("bar")
    line_visualizer = LegacyChartGeneratorAdapter("line")
    
    data = [12, 18, 25, 32, 28, 35, 42]
    
    # צור מערכות ניתוח נתונים עם כלי המחשה שונים
    bar_system = AnalyticsSystem(processor, bar_visualizer)
    line_system = AnalyticsSystem(LegacyDataAnalyzerAdapter(), line_visualizer)
    
    # הרץ ניתוחים
    bar_result = bar_system.analyze_and_visualize(data, "bar_chart.png")
    line_result = line_system.analyze_and_visualize(data, "line_chart.png")
    
    print("Complete workflow test completed")
    print(f"Bar chart result: {bar_result['visualization_file']}")
    print(f"Line chart result: {line_result['visualization_file']}")
    
    # קבל סיכומים
    print("Bar system summary:")
    print(bar_system.get_analysis_summary())
    print("Line system summary:")
    print(line_system.get_analysis_summary())
quiz iconבחנו את עצמכם

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

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

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