Menu
Coddy logo textTech

Adaptör Kalıbı

Coddy'nin Python Journey'sinin Object Oriented Programming bölümünün bir parçası — ders 50 / 64.

Adapter (Adaptör) Deseni, uyumsuz arayüzlere sahip nesnelerin birlikte çalışmasına olanak tanır. Mevcut bir sınıfı, istemcilerin beklediği yeni bir arayüzle sarmalayarak bir köprü görevi görür.

İşte uyumsuz arayüzlere sahip iki sistem:

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

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

Eski yazıcı old_print() kullanırken, yenisi print() kullanıyor.

Eski yazıcının yeni arayüzle çalışmasını sağlamak için bir adaptör oluşturun:

class PrinterAdapter:
    def __init__(self, old_printer):
        self.old_printer = old_printer
    
    def print(self, text):
        # Eski arayüzü yeni arayüze uyarla
        return self.old_printer.old_print(text)

Adaptör, eski yazıcıyı sarmalar ve beklenen arayüzü sağlar.

Her iki yazıcıyı da aynı istemci koduyla kullanın:

def print_document(printer, text):
    return printer.print(text)  # print() metodunu bekler

# Yeni yazıcıyı doğrudan kullanın
new_printer = NewPrinter()
print(print_document(new_printer, "Hello"))

# Eski yazıcıyı adaptör aracılığıyla kullanın
old_printer = OldPrinter()
adapter = PrinterAdapter(old_printer)
print(print_document(adapter, "Hello"))

Medya oynatıcıları ile başka bir örnek oluşturalım:

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"))

Çıktı:

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

Anahtar Nokta: Adapter (Adaptör) Deseni, mevcut bir sınıfı yeni bir arayüzle sarmalayarak uyumsuz arayüzlerin birlikte çalışmasını sağlar. Adaptör, beklenen arayüzden gelen çağrıları, sarmalanan nesnenin gerçek arayüzüne çevirir. Bu, mevcut kodu değiştirmeden eski kodları veya üçüncü taraf kütüphaneleri entegre etmek için kullanışlıdır.

challenge icon

Görev

Orta

Bu meydan okumada, eski sistemleri modern bir uygulama mimarisiyle entegre etmek için Adapter tasarım desenini uygulayacaksınız. Adapter deseni, bir arayüzü diğerine çeviren bir sarmalayıcı (adapter) oluşturarak uyumsuz arayüzlere sahip nesnelerin birlikte çalışmasına olanak tanır.

 

Şirketinizin, yeni bir modern analitik platformuyla entegre edilmesi gereken eski bir veri analizi ve görselleştirme sistemi var. Eski bileşenler, yeni sistemle uyumsuz arayüzlere sahiptir. Eski kodu yeniden yazmak yerine (ki bu riskli ve pahalı olurdu), bu bileşenlerin yeni sistemle çalışmasını sağlayacak adaptörler oluşturmakla görevlendirildiniz.

Şunları yapmanız gerekiyor:

  1. interfaces.py dosyasında tanımlanan modern arayüzleri anlayın (bu dosya değiştirilemez)
  2. legacy_system.py dosyasındaki eski bileşenleri inceleyin (bu dosya değiştirilemez)
  3. adapters.py dosyasında, eski bileşenleri modern arayüzlerle uyumlu hale getiren adaptör sınıflarını uygulayın
  4. modern_system.py dosyasında bu arayüzleri kullanan modern bir sistem oluşturun

Kopya kağıdı

Adapter Deseni, mevcut bir sınıfı istemcilerin beklediği yeni bir arayüzle sarmalayarak, uyumsuz arayüzlere sahip nesnelerin birlikte çalışmasına olanak tanır.

Temel adapter yapısı:

class PrinterAdapter:
    def __init__(self, old_printer):
        self.old_printer = old_printer
    
    def print(self, text):
        # Eski arayüzü yeni arayüze uyarla
        return self.old_printer.old_print(text)

Uyumsuz yazıcı arayüzleri ile örnek:

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

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

# İstemci kodu print() metodunu bekler
def print_document(printer, text):
    return printer.print(text)

# Eski yazıcıyı adapter aracılığıyla kullan
old_printer = OldPrinter()
adapter = PrinterAdapter(old_printer)
print(print_document(adapter, "Hello"))  # OLD: Hello

Medya oynatıcı adapter örneği:

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)

Adapter, beklenen arayüzden gelen çağrıları sarmalanan nesnenin gerçek arayüzüne çevirerek, eski kodun (legacy code) değişiklik yapılmadan entegrasyonunu sağlar.

Kendin dene

# Gerekli tüm sınıfları içe aktar
from adapters import LegacyDataAnalyzerAdapter, LegacyChartGeneratorAdapter
from modern_system import AnalyticsSystem

# Kapsamlı test senaryosu işleyicisi
test_case = input()

if test_case == "basic_adapter_test":
    # Temel adaptör işlevselliğini test et
    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":
    # Görselleştirici adaptörünü test et
    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":
    # Tam analitik sistemini test et
    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":
    # Doğrulama hatalarını test et
    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":
    # Boş veri ile test et
    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":
    # Farklı grafik türlerini test et
    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":
    # Dosya uzantısı yönetimini test et
    visualizer = LegacyChartGeneratorAdapter()
    data = [1, 2, 3, 4]
    visualizer.visualize(data)
    
    # Çeşitli dosya adı formatlarını test et
    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":
    # Analiz özetini test et
    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":
    # Karışık sayısal verilerle test et
    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":
    # Geçersiz sayısal verilerle test et
    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":
    # Sonuç içermeyen özeti test et
    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":
    # Daha büyük veri seti ile test et
    processor = LegacyDataAnalyzerAdapter()
    data = list(range(1, 101))  # 1'den 100'e kadar
    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":
    # Birden fazla işlem içeren tam iş akışını test et
    processor = LegacyDataAnalyzerAdapter()
    bar_visualizer = LegacyChartGeneratorAdapter("bar")
    line_visualizer = LegacyChartGeneratorAdapter("line")
    
    data = [12, 18, 25, 32, 28, 35, 42]
    
    # Farklı görselleştiricilerle analitik sistemleri oluştur
    bar_system = AnalyticsSystem(processor, bar_visualizer)
    line_system = AnalyticsSystem(LegacyDataAnalyzerAdapter(), line_visualizer)
    
    # Analizleri çalıştır
    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']}")
    
    # Özetleri al
    print("Bar system summary:")
    print(bar_system.get_analysis_summary())
    print("Line system summary:")
    print(line_system.get_analysis_summary())
quiz iconKendini test et

Bu ders kısa bir quiz içerir. Soruları yanıtlamak ve ilerlemeni kaydetmek için derse başla.

Object Oriented Programming bölümündeki tüm dersler