← Назад к вопросам

Приведи пример использования паттернов программирования

2.0 Middle🔥 151 комментариев
#Python Core#Архитектура и паттерны

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Примеры использования паттернов программирования

Я продемонстрирую практическое применение основных паттернов с реальными примерами.

1. Singleton (Одиночка)

Используется для единого объекта (конфиг, база данных, логгер):

import logging
from functools import lru_cache

# Паттерн Singleton через decorator
class DatabaseConnection:
    _instance = None
    
    def __new__(cls):
        if cls._instance is None:
            cls._instance = super().__new__(cls)
            cls._instance._connection = None
        return cls._instance
    
    def connect(self, url):
        if self._connection is None:
            self._connection = f"Connected to {url}"
            return self._connection
        return self._connection

# Использование
db1 = DatabaseConnection()
db2 = DatabaseConnection()
assert db1 is db2  # Один и тот же объект

db1.connect("postgres://localhost")
print(db2._connection)  # Данные доступны

2. Factory (Фабрика)

Создание объектов без привязки к их конкретным классам:

from abc import ABC, abstractmethod

class Payment(ABC):
    @abstractmethod
    def pay(self, amount):
        pass

class CreditCardPayment(Payment):
    def pay(self, amount):
        return f"Оплачено {amount}р кредитной картой"

class PayPalPayment(Payment):
    def pay(self, amount):
        return f"Оплачено {amount}р через PayPal"

class PaymentFactory:
    """Фабрика для создания платежей"""
    @staticmethod
    def create(payment_type: str) -> Payment:
        if payment_type == "card":
            return CreditCardPayment()
        elif payment_type == "paypal":
            return PayPalPayment()
        else:
            raise ValueError(f"Unknown payment type: {payment_type}")

# Использование
factory = PaymentFactory()
payment = factory.create("card")
print(payment.pay(1000))  # Оплачено 1000р кредитной картой

payment = factory.create("paypal")
print(payment.pay(500))   # Оплачено 500р через PayPal

3. Builder (Строитель)

Поэтапное построение сложного объекта:

class QueryBuilder:
    """Builder для конструирования SQL запросов"""
    
    def __init__(self):
        self._select = "*"
        self._from = None
        self._where = None
        self._limit = None
    
    def select(self, columns: str):
        self._select = columns
        return self
    
    def from_table(self, table: str):
        self._from = table
        return self
    
    def where(self, condition: str):
        self._where = condition
        return self
    
    def limit(self, count: int):
        self._limit = count
        return self
    
    def build(self) -> str:
        if not self._from:
            raise ValueError("FROM clause is required")
        
        query = f"SELECT {self._select} FROM {self._from}"
        if self._where:
            query += f" WHERE {self._where}"
        if self._limit:
            query += f" LIMIT {self._limit}"
        return query

# Использование
query = (QueryBuilder()
    .select("id, name, email")
    .from_table("users")
    .where("age > 18")
    .limit(10)
    .build())

print(query)
# SELECT id, name, email FROM users WHERE age > 18 LIMIT 10

4. Observer (Наблюдатель)

Подписка на события и уведомления:

from typing import List
from abc import ABC, abstractmethod

class Observer(ABC):
    @abstractmethod
    def update(self, message: str):
        pass

class Subject:
    """Издатель событий"""
    
    def __init__(self):
        self._observers: List[Observer] = []
    
    def attach(self, observer: Observer):
        if observer not in self._observers:
            self._observers.append(observer)
    
    def detach(self, observer: Observer):
        self._observers.remove(observer)
    
    def notify(self, message: str):
        for observer in self._observers:
            observer.update(message)

class EmailSubscriber(Observer):
    def update(self, message: str):
        print(f"Email: получено сообщение: {message}")

class SMSSubscriber(Observer):
    def update(self, message: str):
        print(f"SMS: получено сообщение: {message}")

# Использование
subject = Subject()
email = EmailSubscriber()
sms = SMSSubscriber()

subject.attach(email)
subject.attach(sms)

subject.notify("Новое событие!")  # Оба получат уведомление

5. Strategy (Стратегия)

Выбор алгоритма во время выполнения:

from abc import ABC, abstractmethod

class SortingStrategy(ABC):
    @abstractmethod
    def sort(self, data: list):
        pass

class BubbleSort(SortingStrategy):
    def sort(self, data: list):
        n = len(data)
        for i in range(n):
            for j in range(0, n - i - 1):
                if data[j] > data[j + 1]:
                    data[j], data[j + 1] = data[j + 1], data[j]
        return data

class QuickSort(SortingStrategy):
    def sort(self, data: list):
        if len(data) <= 1:
            return data
        pivot = data[0]
        less = [x for x in data[1:] if x <= pivot]
        greater = [x for x in data[1:] if x > pivot]
        return self.sort(less) + [pivot] + self.sort(greater)

class DataSorter:
    def __init__(self, strategy: SortingStrategy):
        self.strategy = strategy
    
    def sort_data(self, data: list):
        return self.strategy.sort(data)

# Использование
data = [5, 2, 8, 1, 9]

sorter = DataSorter(BubbleSort())
print(sorter.sort_data(data.copy()))  # [1, 2, 5, 8, 9]

sorter = DataSorter(QuickSort())
print(sorter.sort_data(data.copy()))  # [1, 2, 5, 8, 9]

6. Decorator (Декоратор)

Добавление функциональности к объектам:

from abc import ABC, abstractmethod

class Coffee(ABC):
    @abstractmethod
    def cost(self):
        pass
    
    @abstractmethod
    def description(self):
        pass

class SimpleCoffee(Coffee):
    def cost(self):
        return 5.0
    
    def description(self):
        return "Простой кофе"

class CoffeeDecorator(Coffee):
    def __init__(self, coffee: Coffee):
        self._coffee = coffee

class MilkDecorator(CoffeeDecorator):
    def cost(self):
        return self._coffee.cost() + 1.5
    
    def description(self):
        return self._coffee.description() + ", молоко"

class SugarDecorator(CoffeeDecorator):
    def cost(self):
        return self._coffee.cost() + 0.5
    
    def description(self):
        return self._coffee.description() + ", сахар"

# Использование
coffee = SimpleCoffee()
print(f"{coffee.description()}: {coffee.cost()}р")
# Простой кофе: 5.0р

coffee = MilkDecorator(coffee)
print(f"{coffee.description()}: {coffee.cost()}р")
# Простой кофе, молоко: 6.5р

coffee = SugarDecorator(coffee)
print(f"{coffee.description()}: {coffee.cost()}р")
# Простой кофе, молоко, сахар: 7.0р

7. Command (Команда)

Инкапсуляция запросов в объекты:

from abc import ABC, abstractmethod
from typing import List

class Command(ABC):
    @abstractmethod
    def execute(self):
        pass
    
    @abstractmethod
    def undo(self):
        pass

class LightOnCommand(Command):
    def __init__(self, light):
        self.light = light
    
    def execute(self):
        self.light.turn_on()
    
    def undo(self):
        self.light.turn_off()

class Light:
    def turn_on(self):
        print("Свет включен")
    
    def turn_off(self):
        print("Свет выключен")

class RemoteControl:
    def __init__(self):
        self._commands: List[Command] = []
        self._history: List[Command] = []
    
    def execute(self, command: Command):
        command.execute()
        self._history.append(command)
    
    def undo(self):
        if self._history:
            command = self._history.pop()
            command.undo()

# Использование
light = Light()
remote = RemoteControl()

command = LightOnCommand(light)
remote.execute(command)  # Свет включен
remote.undo()            # Свет выключен

8. Adapter (Адаптер)

Приведение несовместимых интерфейсов:

class OldPaymentGateway:
    def process_charge(self, amount_cents):
        return f"Обработано {amount_cents} центов"

class NewPaymentInterface:
    def pay(self, amount_dollars):
        pass

class PaymentAdapter(NewPaymentInterface):
    def __init__(self, old_gateway: OldPaymentGateway):
        self.old_gateway = old_gateway
    
    def pay(self, amount_dollars):
        amount_cents = int(amount_dollars * 100)
        return self.old_gateway.process_charge(amount_cents)

# Использование
old_gateway = OldPaymentGateway()
adapter = PaymentAdapter(old_gateway)

result = adapter.pay(10.50)  # 10.50 доллара
print(result)  # Обработано 1050 центов

9. Facade (Фасад)

Упрощение сложной системы:

class Engine:
    def start(self):
        return "Двигатель запущен"

class Transmission:
    def shift(self):
        return "Включена 1-я передача"

class Lights:
    def turn_on(self):
        return "Фары включены"

class Car:
    """Фасад для сложной системы автомобиля"""
    
    def __init__(self):
        self.engine = Engine()
        self.transmission = Transmission()
        self.lights = Lights()
    
    def start_car(self):
        print(self.lights.turn_on())
        print(self.engine.start())
        print(self.transmission.shift())
        return "Машина готова к движению"

# Использование
car = Car()
print(car.start_car())
# Фары включены
# Двигатель запущен
# Включена 1-я передача
# Машина готова к движению

10. Template Method (Шаблонный метод)

Определение скелета алгоритма в базовом классе:

from abc import ABC, abstractmethod

class DataProcessor(ABC):
    """Шаблонный метод для обработки данных"""
    
    def process(self, data):
        raw = self.read(data)
        cleaned = self.clean(raw)
        transformed = self.transform(cleaned)
        return self.output(transformed)
    
    @abstractmethod
    def read(self, data):
        pass
    
    def clean(self, data):
        return data  # Default
    
    @abstractmethod
    def transform(self, data):
        pass
    
    def output(self, data):
        return data  # Default

class CSVProcessor(DataProcessor):
    def read(self, data):
        return data.split(",")
    
    def clean(self, data):
        return [x.strip() for x in data]
    
    def transform(self, data):
        return [x.upper() for x in data]

# Использование
processor = CSVProcessor()
result = processor.process("john, jane, mike")
print(result)  # ["JOHN", "JANE", "MIKE"]

Когда какой паттерн использовать

  • Singleton — конфиг, логгер, БД
  • Factory — создание разных типов объектов
  • Builder — построение сложных объектов
  • Observer — события и подписки
  • Strategy — выбор алгоритма
  • Decorator — добавление функциональности
  • Command — отмена операций, очереди
  • Adapter — совместимость интерфейсов
  • Facade — упрощение сложности
  • Template Method — шаблоны для подклассов

Ключевой момент: не переусложняй. Используй паттерны когда они решают реальные проблемы, а не для их же ради.