Ответ
GRASP (General Responsibility Assignment Software Patterns — Общие паттерны распределения обязанностей в ПО) — это набор принципов и рекомендаций для распределения обязанностей между классами и объектами в объектно-ориентированном проектировании. Их основная цель — создание гибких, понятных, легко поддерживаемых и расширяемых систем.
Основные паттерны GRASP:
- Информационный эксперт (Information Expert): Назначать ответственность классу, который владеет всей необходимой информацией для выполнения этой ответственности. Это способствует высокой связности и низкой связанности.
- Создатель (Creator): Класс, создающий объекты, должен их содержать, агрегировать или тесно использовать. Это упрощает управление зависимостями и инкапсулирует логику создания.
- Контроллер (Controller): Использовать промежуточный класс для обработки системных событий или операций, делегируя их выполнение другим объектам. Это отделяет пользовательский интерфейс от бизнес-логики.
- Низкая связанность (Low Coupling): Минимизировать зависимости между классами. Низкая связанность делает систему более устойчивой к изменениям, легче тестируемой и повторно используемой.
- Высокая связность (High Cohesion): Группировать связанные обязанности в одном классе. Высокая связность улучшает читаемость, управляемость и повторное использование кода.
- Полиморфизм (Polymorphism): Использовать полиморфизм для обработки альтернативных вариантов поведения на основе типа объекта, а не условных операторов. Это упрощает расширение системы новыми типами.
- Чистая выдумка (Pure Fabrication): Создавать искусственные классы, не соответствующие доменной модели, для соблюдения принципов высокой связности и низкой связанности, когда другие паттерны не применимы.
- Индеректность (Indirection): Добавлять промежуточный объект для развязки двух других элементов, чтобы уменьшить их прямую связанность и повысить гибкость.
- Устойчивость к изменениям (Protected Variations): Защищать элементы от изменений других элементов, используя интерфейсы, полиморфизм и индиректность. Это позволяет изолировать изменения.
Пример: Информационный эксперт
Класс Order
является информационным экспертом для расчета общей стоимости, так как он владеет списком items
и их свойствами.
class Item:
def __init__(self, price: float, quantity: int):
self.price = price
self.quantity = quantity
class Order:
def __init__(self, items: list[Item]):
self.items = items
def calculate_total(self) -> float:
"""Рассчитывает общую стоимость заказа."""
# Order знает свои items, поэтому логично считать сумму здесь
return sum(item.price * item.quantity for item in self.items)
# Использование:
item1 = Item(price=10.0, quantity=2)
item2 = Item(price=5.5, quantity=3)
order = Order(items=[item1, item2])
print(f"Общая стоимость заказа: {order.calculate_total():.2f}") # Вывод: 36.50
Применение GRASP-паттернов помогает создавать более гибкие, понятные и легко поддерживаемые объектно-ориентированные системы, улучшая их архитектуру и качество кода.