Паттерны проектирования

Что такое паттерны проектирования?

подробнее

Паттерны проектирования в программировании - это типовые решения часто встречающихся задач при создании программного обеспечения. Это шаблоны, которые позволяют систематизировать подход к построению программ и повысить качество архитектуры.

Классификация паттернов проектирования

подробнее
  • Порождающие (Creational)
    Про способы создания объектов и изоляцию клиента от конкретных классов. Примеры: Singleton, Factory Method, Abstract Factory, Builder, Prototype.
  • Структурные (Structural)
    Про организацию связей между частями системы и разумную композицию. Примеры: Adapter, Composite, Decorator, Facade, Proxy, Bridge.
  • Поведенческие (Behavioral)
    Про правила взаимодействия и распределение обязанностей. Примеры: Observer, Strategy, Command, State, Iterator, Chain of Responsibility, Mediator.

Singleton

подробнее

Singleton - это паттерн, который гарантирует, что у класса есть только один экземпляр, и предоставляет к нему глобальную точку доступа (например, для настроек или подключения к БД).

Примеры:

# реализация через __new__
class Singleton:
    _instance = None

    def __new__(cls):
        if cls._instance is None:
            cls._instance = super().__new__(cls)
        return cls._instance
# реализация через импорт из модуля

# db.py
class Database:
    ...
connection = Database() # Импортируй эту переменную везде

# my_module.py
from db import connection

Dependency Injection

подробнее

Dependency Injection (DI, Внедрение зависимостей) - это паттерн, при котором объект не создает зависимые объекты сам, а получает их извне (обычно через конструктор).

Примеры:

  • Без DI (Жесткая связь)
    Класс сам создает базу. Если захотим сменить БД на тестовую — придется переписывать класс

      class UserService:
          def __init__(self):
              self.db = MySQLDatabase() # Плохо: привязаны к конкретной БД
    
  • С DI (Гибкая связь)
    Мы «вбрасываем» зависимость при создании.

      class UserService:
          def __init__(self, db):
              self.db = db # Хорошо: принимаем любой объект с нужным интерфейсом
        
      # Теперь мы сами решаем, что передать:
      service = UserService(MySQLDatabase()) 
      # или для тестов:
      test_service = UserService(MockDatabase())
    

Factory

подробнее

Фабрика (Factory) - это порождающий паттерн, который предоставляет единый интерфейс для создания объектов, скрывая логику их инициализации.
Вместо того чтобы повсюду писать ClassName(), вызывается «создатель», который сам решает, какой объект вернуть (например на основе конфига).

2 основных вида в Python

  • Простая фабрика (Simple Factory)
    Обычная функция или класс, который через if-elif или словарь выбирает, какой объект создать.

      class Dog: 
          def speak(self): return "Гав!"
      class Cat: 
          def speak(self): return "Мяу!"
        
      def get_pet(pet_type):
          pets = {"dog": Dog, "cat": Cat}
          return pets[pet_type]() # Создаем нужный объект
    
  • Фабричный метод (Factory Method)
    Классический паттерн, где базовый класс определяет интерфейс создания, а подклассы решают, какой именно объект инстанцировать.
    Это позволяет добавлять новых «животных», не меняя основной код логики.

      from abc import ABC, abstractmethod
        
      # 1. Общий интерфейс продукта
      class Animal(ABC):
          @abstractmethod
          def speak(self): pass
        
      class Dog(Animal):
          def speak(self): return "Гав!"
        
      class Cat(Animal):
          def speak(self): return "Мяу!"
        
      # 2. Базовый класс-СОЗДАТЕЛЬ (Фабрика)
      class AnimalFactory(ABC):
          @abstractmethod
          def create_animal(self) -> Animal:
              """Тот самый фабричный метод"""
              pass
        
          def make_sound(self):
              # Логика работает с абстракцией, а не с конкретным классом
              animal = self.create_animal()
              return animal.speak()
        
      # 3. Конкретные создатели
      class DogFactory(AnimalFactory):
          def create_animal(self): return Dog()
        
      class CatFactory(AnimalFactory):
          def create_animal(self): return Cat()
        
      # Использование:
      factory = DogFactory()
      print(factory.make_sound()) # "Гав!"