Какие существуют структурные паттерны проектирования?

Ответ

Структурные паттерны проектирования помогают организовать классы и объекты в более крупные структуры, сохраняя гибкость, эффективность и упрощая взаимодействие между компонентами. Они описывают, как объекты и классы могут быть скомпонованы для формирования больших структур.

Основные структурные паттерны:

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

    • Что делает: Преобразует интерфейс одного класса в другой интерфейс, ожидаемый клиентом, позволяя классам с несовместимыми интерфейсами работать вместе.
    • Когда использовать: Когда нужно интегрировать существующий класс, который имеет неподходящий интерфейс, в новую систему.
    • Пример:
      
      # Несовместимый класс
      class OldSystem:
      def old_request(self):
          return "Data from Old System"

    Ожидаемый интерфейс

    class NewSystemTarget: def request(self): pass

    Адаптер

    class Adapter(NewSystemTarget): def init(self, old_system_instance): self._old_system = old_system_instance

    def request(self):
        return f"Adapter: {self._old_system.old_request()}"

    Использование

    old_obj = OldSystem() adapter = Adapter(old_obj) print(adapter.request()) # Adapter: Data from Old System

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

    • Что делает: Динамически добавляет объекту новую функциональность, оборачивая его в объект-декоратор. Это гибкая альтернатива наследованию для расширения функционала.
    • Когда использовать: Когда нужно добавить или удалить обязанности объекта во время выполнения, не изменяя его структуру.
    • Пример:
      
      class Coffee:
      def get_cost(self): return 5
      def get_ingredients(self): return "Coffee"

    class MilkDecorator: def init(self, coffee): self._coffee = coffee def get_cost(self): return self._coffee.get_cost() + 2 def get_ingredients(self): return self._coffee.get_ingredients() + ", Milk"

    my_coffee = Coffee() my_coffee = MilkDecorator(my_coffee) print(f"Cost: {my_coffee.get_cost()}, Ingredients: {my_coffee.get_ingredients()}")

    Cost: 7, Ingredients: Coffee, Milk

  3. Фасад (Facade)

    • Что делает: Предоставляет унифицированный (упрощенный) интерфейс к сложной подсистеме, скрывая ее сложность.
    • Когда использовать: Когда система состоит из множества взаимосвязанных классов, и нужно предоставить простой способ взаимодействия с ней.
  4. Компоновщик (Composite)

    • Что делает: Позволяет группировать объекты в древовидные структуры и работать с ними как с отдельными объектами. Клиент может единообразно обращаться как к отдельным объектам, так и к их группам.
    • Когда использовать: Когда нужно представить иерархию объектов "часть-целое" и позволить клиентам игнорировать разницу между отдельными объектами и их композициями.
  5. Заместитель (Proxy)

    • Что делает: Предоставляет суррогат или заполнитель для другого объекта, контролируя доступ к нему. Это позволяет добавить дополнительную логику (например, ленивую инициализацию, кэширование, контроль доступа) перед доступом к реальному объекту.
    • Когда использовать: Когда нужен более контролируемый или отложенный доступ к объекту.
  6. Мост (Bridge)

    • Что делает: Разделяет абстракцию и реализацию, позволяя им изменяться независимо друг от друга. Это достигается путем вынесения реализации в отдельную иерархию.
    • Когда использовать: Когда нужно избежать постоянной привязки абстракции к ее реализации или когда и абстракция, и реализация должны расширяться независимо.
  7. Приспособленец (Flyweight)

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