Ответ
В Python-разработке активно применяются различные паттерны проектирования для создания гибкого, масштабируемого и поддерживаемого кода. Ниже представлены некоторые из наиболее часто используемых:
-
Singleton (Одиночка)
- Назначение: Гарантирует, что у класса есть только один экземпляр, и предоставляет глобальную точку доступа к нему.
-
Применение: Используется для объектов, которые должны быть уникальными в системе, например, менеджеры конфигурации, пулы соединений или логирование.
class Singleton: _instance = None def __new__(cls): if not cls._instance: cls._instance = super().__new__(cls) return cls._instance
Пример использования:
s1 = Singleton() s2 = Singleton() print(s1 is s2) # Выведет True
-
Factory Method (Фабричный метод)
- Назначение: Определяет интерфейс для создания объекта, но позволяет подклассам решать, какой класс инстанцировать. Делегирует создание объектов подклассам.
- Применение: Используется, когда класс не может предвидеть класс объектов, которые ему нужно создать, или когда подклассы должны определять, какие объекты создавать.
from abc import ABC, abstractmethod
class Product(ABC): @abstractmethod def operation(self): pass
class ConcreteProduct(Product): def operation(self): return "ConcreteProduct operation"
class Creator(ABC): @abstractmethod def factory_method(self) -> Product: pass
class ConcreteCreator(Creator): def factory_method(self) -> Product: return ConcreteProduct()
Пример использования:
creator = ConcreteCreator() product = creator.factory_method() print(product.operation())
-
Observer (Наблюдатель)
- Назначение: Определяет зависимость "один-ко-многим" между объектами так, что при изменении состояния одного объекта все зависящие от него оповещаются и автоматически обновляются.
-
Применение: Используется для реализации распределенных систем событий, где изменения в одном объекте должны вызывать действия в других, не связывая их напрямую.
class Subject: def __init__(self): self._observers = [] def attach(self, observer): if observer not in self._observers: self._observers.append(observer) def detach(self, observer): self._observers.remove(observer) def notify(self, message): for observer in self._observers: observer.update(message)
class Observer: def init(self, name): self.name = name
def update(self, message): print(f"Observer {self.name} received: {message}")Пример использования:
subject = Subject() observer1 = Observer("One") observer2 = Observer("Two")
subject.attach(observer1) subject.attach(observer2)
subject.notify("State changed!")
-
Decorator (Декоратор)
- Назначение: Динамически добавляет новую функциональность объекту, не изменяя его структуру. В Python реализуется с помощью функций-декораторов или классов.
- Применение: Идеален для добавления логирования, кэширования, проверки прав доступа, измерения времени выполнения и других сквозных функций.
def logger(func): def wrapper(*args, **kwargs): print(f"[LOG] Calling function: {func.__name__} with args: {args}, kwargs: {kwargs}") result = func(*args, **kwargs) print(f"[LOG] Function {func.__name__} returned: {result}") return result return wrapper
@logger def add(a, b): return a + b
Пример использования:
print(add(2, 3))
Помимо перечисленных, в Python также часто используются другие паттерны, такие как Adapter (Адаптер), Strategy (Стратегия), Facade (Фасад), Iterator (Итератор) и Template Method (Шаблонный метод).
Ответ 18+ 🔞
А, паттерны проектирования! Ну это ж, блядь, как священные скрижали для любого питониста, который хочет выглядеть умно на совещании. Сидишь такой, киваешь: "Да-да, тут у нас фабрика, там наблюдатель, а вот тут, сука, декоратор прилепил — красота!" А сам думаешь: "Главное — не перепутать, какой из них за что отвечает, а то опозоришься, как полупидор".
Ну ладно, поехали разбирать эту матчасть, чтоб тебя не разоблачили, как хитрожопого самозванца.
1. Singleton (Одиночка)
Назначение: Чтобы какой-нибудь наглый объект не плодился, как кролики, по всей твоей программе. Гарантирует, что экземпляр класса будет один, и все будут тыкать в него пальцем, как в глобальную переменную, но при этом прилично. Где впихнуть: Ну, например, когда у тебя конфиг один на всю систему, а не десять разных, которые между собой дерутся, как пизда с ушами. Или логгер, чтобы он не писал в десять файлов одновременно, создавая пиздец и хаос.
class Singleton:
_instance = None
def __new__(cls):
if not cls._instance:
cls._instance = super().__new__(cls)
return cls._instance
# Пример использования:
s1 = Singleton()
s2 = Singleton()
print(s1 is s2) # Выведет True — это один и тот же ушлёпок, а не два разных!
2. Factory Method (Фабричный метод)
Назначение: Это когда ты не хочешь пачкать руки, создавая объекты напрямую через new. Говоришь какому-то другому классу: "Слушай, дружок, роди мне тут штуку, а я сам не буду разбираться, как её правильно собирать". А он тебе: "Да не вопрос, ща нафабрикаю!"
Где впихнуть: Когда у тебя куча похожих объектов, но с разными настройками, и ты не хочешь в основном коде разводить эту грязь с if-elif-else на три экрана.
from abc import ABC, abstractmethod
class Product(ABC):
@abstractmethod
def operation(self):
pass
class ConcreteProduct(Product):
def operation(self):
return "ConcreteProduct operation"
class Creator(ABC):
@abstractmethod
def factory_method(self) -> Product:
pass
class ConcreteCreator(Creator):
def factory_method(self) -> Product:
return ConcreteProduct()
# Пример использования:
creator = ConcreteCreator()
product = creator.factory_method()
print(product.operation()) # А вот и твой свежеиспечённый продукт, получай!
3. Observer (Наблюдатель)
Назначение: Представь, что у тебя есть один важный чувак (Subject), а вокруг него куча подписчиков (Observers), которые ждут, не дождутся, когда он чихнёт, чтобы сразу побежать за носовым платком. Как только он меняется — все они тут как тут. Где впихнуть: Идеально для всяких систем событий. Например, пользователь нажал кнопку — и сразу десять разных модулей про это узнали и что-то сделали. Без этой хуйни пришлось бы всё вручную дергать, а тут — красота, один раз оповестил, и все в курсе.
class Subject:
def __init__(self):
self._observers = []
def attach(self, observer):
if observer not in self._observers:
self._observers.append(observer)
def detach(self, observer):
self._observers.remove(observer)
def notify(self, message):
for observer in self._observers:
observer.update(message)
class Observer:
def __init__(self, name):
self.name = name
def update(self, message):
print(f"Observer {self.name} received: {message}")
# Пример использования:
subject = Subject()
observer1 = Observer("One")
observer2 = Observer("Two")
subject.attach(observer1)
subject.attach(observer2)
subject.notify("State changed!") # И оба наблюдателя тут же охуели от новости.
4. Decorator (Декоратор)
Назначение: Это как наклейки на ноутбук. Хочешь добавить функциональность — прилепил декоратор. Не понравилось — отклеил. А сам ноутбук (функция) даже не в курсе, что его разукрасили.
Где впихнуть: О, это любовь всех питонистов! Захотел залогировать вызов функции — обернул в @logger. Захотел закэшировать результат — @lru_cache из коробки. Всё, блядь, чисто и красиво, без копипасты одного и того же кода в каждую функцию.
def logger(func):
def wrapper(*args, **kwargs):
print(f"[LOG] Calling function: {func.__name__} with args: {args}, kwargs: {kwargs}")
result = func(*args, **kwargs)
print(f"[LOG] Function {func.__name__} returned: {result}")
return result
return wrapper
@logger
def add(a, b):
return a + b
# Пример использования:
print(add(2, 3))
# Выведет кучу логирования, а потом результат. Удобно же, ёпта!
Ну и конечно, есть ещё овердохуища других паттернов: Адаптер (чтобы старый кривой код притворился новым), Стратегия (меняешь алгоритм на лету, как перчатки), Фасад (прячешь за красивой дверью трёхэтажный пиздец) и так далее.
Главное — не пытайся впихнуть их все в один проект, а то получится не архитектура, а ёперный театр, где каждый класс думает, что он главный. Используй с умом, и будет тебе счастье.