Что такое паттерн 'Приспособленец' (Flyweight)?
Sobes Copilot
Получайте ответы в реальном времени
Ответ от нейросети
sobes.tech AI
"Приспособленец" (Flyweight) — это структурный паттерн проектирования, позволяющий эффективно использовать множество мелких объектов, значительно уменьшая потребление памяти. Он достигается за счет разделения состояния объекта на внутреннее (intrinsic), которое является общим для нескольких объектов и хранится в самом приспособленце, и внешнее (extrinsic), которое уникально для каждого конкретного контекста использования и передается приспособленцу извне. Паттерн применяется, когда есть большое количество объектов одного класса с почти одинаковым состоянием.
Ключевые компоненты:
- Flyweight (Приспособленец): Интерфейс или абстрактный класс, определяющий методы, которые могут принимать внешнее состояние.
- ConcreteFlyweight (Конкретный Приспособленец): Реализация Flyweight, содержащая внутреннее состояние.
- FlyweightFactory (Фабрика Приспособленцев): Создает и управляет объектами ConcreteFlyweight. Она гарантирует, что приспособленцы с одинаковым внутренним состоянием будут переиспользованы, а не созданы заново.
- Client (Клиент): Использует объекты Flyweight и передает им внешнее состояние.
Принцип работы заключается в том, что Клиент запрашивает приспособленца у Фабрики. Фабрика ищет существующий приспособленец с нужным внутренним состоянием. Если находит, возвращает его. Если нет, создает новый, сохраняет его в кеш и возвращает. При использовании приспособленца Клиент передает ему необходимое внешнее состояние в качестве аргументов метода.
Преимущества:
- Уменьшает потребление памяти, особенно при большом количестве объектов.
- Улучшает производительность за счет уменьшения накладных расходов на создание и сборку мусора объектов.
Недостатки:
- Введение паттерна усложняет код.
- Клиент должен явно управлять внешним состоянием.
Пример использования: отображение большого количества однотипных графических элементов в игре или редакторе. Вместо создания отдельного объекта для каждого элемента (с одинаковой текстурой, но разным положением), можно создать один объект-приспособленец для текстуры и передавать ему внешнее состояние (координаты, поворот) при отрисовке.
# Пример интерфейса приспособленца
class TextCharacter:
def display(self, position):
pass # Метод, принимающий внешнее состояние
# Пример конкретного приспособленца (внутреннее состояние - сам символ)
class ConcreteTextCharacter(TextCharacter):
def __init__(self, char):
self._char = char
def display(self, position):
# Использование внутреннего состояния и внешнего состояния (позиции)
print(f"Отображение символа '{self._char}' на позиции {position}")
# Пример фабрики приспособленцев
class CharacterFactory:
_characters = {} # Кеш приспособленцев
def get_character(self, char):
if char not in self._characters:
self._characters[char] = ConcreteTextCharacter(char)
print(f"Создан новый приспособленец для символа '{char}'")
else:
print(f"Использован существующий приспособленец для символа '{char}'")
return self._characters[char]
# Пример использования клиентом
if __name__ == "__main__":
factory = CharacterFactory()
# Клиент получает приспособленцев из фабрики и передает внешнее состояние
char_a1 = factory.get_character('A')
char_a1.display((1, 1))
char_b = factory.get_character('B')
char_b.display((2, 2))
char_a2 = factory.get_character('A') # Повторное использование существующего приспособленца
char_a2.display((3, 3))
# Все объекты 'A' используют один экземпляр ConcreteTextCharacter
print(f"Идентичны a1 и a2? {char_a1 is char_a2}")