Какие паттерны проектирования из GoF наиболее часто применяются в Python

Ответ

Хотя многие паттерны применимы в Python, некоторые используются особенно часто благодаря особенностям языка.

  1. Декоратор (Decorator) В Python этот паттерн реализован на уровне синтаксиса (@decorator), что делает его чрезвычайно популярным для добавления функциональности (логирование, кэширование, проверка прав) к функциям и методам, не изменяя их код.

    import time
    
    def timing_decorator(func):
        def wrapper(*args, **kwargs):
            start_time = time.time()
            result = func(*args, **kwargs)
            end_time = time.time()
            print(f"'{func.__name__}' выполнилась за {end_time - start_time:.4f} секунд")
            return result
        return wrapper
    
    @timing_decorator
    def get_data():
        time.sleep(1)
        return "Some data"
    
    get_data()
    # Вывод: 'get_data' выполнилась за 1.0012 секунд
  2. Фабричный метод (Factory Method) Позволяет создавать объекты, делегируя логику инстанцирования подклассам. Это полезно, когда система должна работать с объектами разных типов, но их точный тип определяется во время выполнения.

    class Document:
        # ... базовый класс
    
    class PdfDocument(Document):
        # ... реализация для PDF
    
    class WordDocument(Document):
        # ... реализация для Word
    
    def get_document_creator(file_extension):
        if file_extension == 'pdf':
            return PdfDocument
        elif file_extension == 'docx':
            return WordDocument
        raise ValueError("Unknown format")
    
    # Использование
    DocCreator = get_document_creator('pdf')
    my_doc = DocCreator()
  3. Стратегия (Strategy) Определяет семейство алгоритмов, инкапсулирует каждый из них и делает их взаимозаменяемыми. Часто используется для реализации различных способов обработки данных (сортировка, экспорт).

    from abc import ABC, abstractmethod
    
    class ExportStrategy(ABC):
        @abstractmethod
        def export(self, data):
            pass
    
    class JsonExport(ExportStrategy):
        def export(self, data):
            print(f"Экспорт в JSON: {data}")
    
    class XMLExport(ExportStrategy):
        def export(self, data):
            print(f"Экспорт в XML: {data}")
    
    # Контекст, использующий стратегию
    class Exporter:
        def __init__(self, strategy: ExportStrategy):
            self._strategy = strategy
    
        def run(self, data):
            self._strategy.export(data)
    
    data_to_export = {"id": 1, "name": "item"}
    exporter = Exporter(JsonExport())
    exporter.run(data_to_export)
  4. Наблюдатель (Observer) Создает механизм подписки, позволяющий одним объектам следить и реагировать на события, происходящие в других объектах. Основа для многих event-driven систем.

  5. Одиночка (Singleton) Гарантирует, что у класса есть только один экземпляр. В Python часто считается антипаттерном, так как его функциональность можно реализовать более идиоматично через модули, которые по своей природе являются синглтонами.