Python | Вопросы собесов
13.8K subscribers
36 photos
1 file
965 links
Download Telegram
📌 Что такое паттерн Заместитель (Proxy)?

💬 Спрашивают в 3% собеседований

Паттерн Заместитель (Proxy) — это структурный шаблон проектирования, который предоставляет объект, управляющий доступом к другому объекту. Этот паттерн создаёт суррогат или заместителя для другого объекта и контролирует доступ к нему.

🤔 Зачем нужен паттерн Заместитель

Паттерн Заместитель используется в следующих случаях:

1️⃣ Управление доступом: Когда необходимо контролировать доступ к ресурсу.

2️⃣ Отложенная инициализация: Когда необходимо отложить создание ресурсоёмких объектов до момента их первого использования.

3️⃣ Управление ресурсами: Для управления ресурсами, такими как память или сетевые соединения.

4️⃣ Логирование и кэширование: Для добавления дополнительной функциональности, такой как логирование или кэширование, без изменения кода основного объекта.

🤔 Типы заместителей

1️⃣ Управляющий заместитель (Virtual Proxy): Контролирует доступ к объекту, создавая его по требованию.

2️⃣ Защитный заместитель (Protection Proxy): Контролирует доступ к объекту, ограничивая права пользователей.

3️⃣ Удалённый заместитель (Remote Proxy): Управляет доступом к объекту, находящемуся в другом адресном пространстве.

4️⃣ Кэш-прокси (Cache Proxy): Кэширует результаты запросов к объекту для повышения производительности.

🤔 Как используется паттерн Заместитель

Заместитель реализует интерфейс основного объекта и перенаправляет вызовы к реальному объекту, добавляя при этом дополнительную функциональность.

🤔 Пример использования

Рассмотрим пример с удалённым заместителем, который управляет доступом к удалённому серверу.
from abc import ABC, abstractmethod

class Subject(ABC):
@abstractmethod
def request(self):
pass

class RealSubject(Subject):
def request(self):
print("Реальный объект: Обработка запроса.")

class Proxy(Subject):
def __init__(self, real_subject):
self._real_subject = real_subject

def request(self):
if self.check_access():
self._real_subject.request()
self.log_access()

def check_access(self):
print("Заместитель: Проверка доступа перед выполнением запроса.")
return True

def log_access(self):
print("Заместитель: Логирование времени запроса.")

# Клиентский код
real_subject = RealSubject()
proxy = Proxy(real_subject)

proxy.request()


В этом примере класс Proxy контролирует доступ к классу RealSubject, добавляя проверку доступа и логирование.

🤔 Подытожим

Паттерн Заместитель управляет доступом к другому объекту, предоставляя дополнительные возможности, такие как контроль доступа, отложенная инициализация, управление ресурсами, логирование и кэширование.

🔥 ТОП ВОПРОСОВ С СОБЕСОВ

🔒 База собесов | 🔒 База тестовых
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4🔥31
📌 Что такое Фабричный метод (Factory method) ?

💬 Спросят с вероятностью 3%

Фабричный метод (Factory Method) — это порождающий паттерн проектирования, который предоставляет интерфейс для создания объектов в суперклассе, позволяя подклассам изменять тип создаваемых объектов. Этот паттерн используется, когда классу заранее неизвестно, объекты каких классов ему нужно создавать, либо он хочет дать возможность своим подклассам выбирать тип создаваемых объектов.

🤔 Зачем нужен данный паттерн?

1️⃣ Изоляция создания объектов: Позволяет суперклассу делегировать создание объектов подклассам, изолируя логику создания объектов от основной логики программы.

2️⃣ Расширяемость: Упрощает добавление новых типов объектов, не изменяя существующий код.

3️⃣ Упрощение тестирования: Легче тестировать классы, так как создание объектов сосредоточено в одном месте.

🤔Как работает данный паттерн?

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

Продукт (Product): Интерфейс или абстрактный класс для объектов, которые будут создаваться.

Конкретный продукт (ConcreteProduct): Конкретные реализации продукта.

Создатель (Creator): Абстрактный класс или интерфейс с объявлением фабричного метода.

Конкретный создатель (ConcreteCreator): Классы, которые реализуют фабричный метод для создания конкретных продуктов.

from abc import ABC, abstractmethod

# Продукт
class Transport(ABC):
@abstractmethod
def deliver(self) -> str:
pass

# Конкретные продукты
class Truck(Transport):
def deliver(self) -> str:
return "Deliver by land in a box."

class Ship(Transport):
def deliver(self) -> str:
return "Deliver by sea in a container."

# Создатель
class Logistics(ABC):
@abstractmethod
def create_transport(self) -> Transport:
pass

def plan_delivery(self) -> str:
transport = self.create_transport()
return transport.deliver()

# Конкретные создатели
class RoadLogistics(Logistics):
def create_transport(self) -> Transport:
return Truck()

class SeaLogistics(Logistics):
def create_transport(self) -> Transport:
return Ship()

# Использование
def client_code(logistics: Logistics):
print(logistics.plan_delivery())

if __name__ == "__main__":
print("App: Launched with the RoadLogistics.")
client_code(RoadLogistics())

print("\nApp: Launched with the SeaLogistics.")
client_code(SeaLogistics())


Преимущества:

1️⃣ Изоляция создания объектов: Создание объектов делегируется подклассам, что изолирует основной код от логики создания объектов.

2️⃣ Расширяемость: Легко добавлять новые продукты, не изменяя существующий код.

3️⃣ Упрощение тестирования: Легко подменять конкретные реализации продуктов для тестирования.

Недостатки:

1️⃣ Усложнение кода: Требует создания большого количества дополнительных классов.

2️⃣ Поддержка иерархии классов: Может усложнить систему, если классы продуктов и создателей становятся слишком сложными.

Паттерн "Фабричный метод" позволяет создавать объекты через интерфейс, делегируя создание конкретных объектов подклассам, что делает код более гибким и расширяемым.

🔥 ТОП ВОПРОСОВ С СОБЕСОВ

🔒 База собесов | 🔒 База тестовых
Please open Telegram to view this post
VIEW IN TELEGRAM
👍71
📌 Что такое паттерн Прототип (Prototype) ?

💬 Спросят с вероятностью 3%

Паттерн "Прототип" (Prototype) — это порождающий паттерн проектирования, который позволяет копировать объекты, не прибегая к их конкретным классам. Он предоставляет механизм для создания новых объектов путем клонирования уже существующих экземпляров-прототипов. Этот паттерн полезен, когда создание объектов требует больших затрат (например, вычислительных или временных), и проще клонировать существующий объект.

🤔 Зачем нужен данный паттерн?

1️⃣ Экономия ресурсов: Избегает затрат на создание нового объекта с нуля, используя существующий объект как шаблон.

2️⃣ Изоляция клиентов от классов продуктов: Позволяет создавать новые объекты без привязки к конкретным классам, что повышает гибкость системы.

3️⃣ Упрощение процесса создания сложных объектов: Легко создавать объекты со сложной конфигурацией, клонируя уже настроенные экземпляры.

🤔 Как работает данный паттерн?

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

Прототип (Prototype): Интерфейс с методом клонирования, который будет реализован конкретными классами.

Конкретный прототип (ConcretePrototype): Классы, которые реализуют метод клонирования для создания копий своих объектов.

Клиент (Client): Использует метод клонирования для создания новых объектов.

import copy
from abc import ABC, abstractmethod

# Прототип
class Prototype(ABC):
@abstractmethod
def clone(self):
pass

# Конкретный прототип
class ConcretePrototype1(Prototype):
def __init__(self, field):
self.field = field

def clone(self):
return copy.deepcopy(self)

def __str__(self):
return f"ConcretePrototype1 with field: {self.field}"

class ConcretePrototype2(Prototype):
def __init__(self, field):
self.field = field

def clone(self):
return copy.deepcopy(self)

def __str__(self):
return f"ConcretePrototype2 with field: {self.field}"

# Использование
if __name__ == "__main__":
prototype1 = ConcretePrototype1("Value1")
prototype2 = ConcretePrototype2("Value2")

clone1 = prototype1.clone()
clone2 = prototype2.clone()

print(prototype1) # ConcretePrototype1 with field: Value1
print(clone1) # ConcretePrototype1 with field: Value1
print(prototype2) # ConcretePrototype2 with field: Value2
print(clone2) # ConcretePrototype2 with field: Value2


Преимущества:

1️⃣ Экономия ресурсов: Быстрое создание новых объектов путем клонирования.

2️⃣ Гибкость: Легко создавать объекты без привязки к конкретным классам.

3️⃣ Упрощение создания сложных объектов: Позволяет клонировать уже настроенные объекты.

Недостатки:

1️⃣ Сложность реализации клонирования: Необходимо правильно реализовать глубокое или поверхностное копирование, что может быть сложно.

2️⃣ Проблемы с копированием объектов: Некоторые объекты могут содержать ссылки на другие, что требует сложных механизмов для правильного клонирования.

Паттерн "Прототип" позволяет быстро и эффективно создавать новые объекты путем клонирования существующих, что упрощает процесс создания сложных объектов и экономит ресурсы.

🔥 ТОП ВОПРОСОВ С СОБЕСОВ

🔒 База собесов | 🔒 База тестовых
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8
📌 Что такое Структурные (Structural) паттерны ?

💬 Спросят с вероятностью 3%

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

🤔 Основные паттерны

1️⃣ Adapter (Адаптер):

Преобразует интерфейс класса в другой интерфейс, ожидаемый клиентом. Позволяет классам работать вместе, которые не могли бы из-за несовместимых интерфейсов.

Использование старого интерфейса библиотеки в новом проекте.

      class OldPrinter:
def print_old(self, text):
print(f"OldPrinter: {text}")

class NewPrinterInterface:
def print(self, text):
pass

class PrinterAdapter(NewPrinterInterface):
def __init__(self, old_printer):
self.old_printer = old_printer

def print(self, text):
self.old_printer.print_old(text)

old_printer = OldPrinter()
adapter = PrinterAdapter(old_printer)
adapter.print("Hello, world!")


2️⃣ Bridge (Мост):

Разделяет абстракцию и её реализацию так, чтобы они могли изменяться независимо друг от друга.

Разделение логики рисования фигуры и конкретных реализаций рисования.

      class DrawingAPI(ABC):
@abstractmethod
def draw_circle(self, x, y, radius):
pass

class DrawingAPI1(DrawingAPI):
def draw_circle(self, x, y, radius):
print(f"API1.circle at {x}:{y} radius {radius}")

class DrawingAPI2(DrawingAPI):
def draw_circle(self, x, y, radius):
print(f"API2.circle at {x}:{y} radius {radius}")

class Circle:
def __init__(self, x, y, radius, drawing_api):
self.x = x
self.y = y
self.radius = radius
self.drawing_api = drawing_api

def draw(self):
self.drawing_api.draw_circle(self.x, self.y, self.radius)

circle1 = Circle(1, 2, 3, DrawingAPI1())
circle2 = Circle(5, 7, 11, DrawingAPI2())

circle1.draw()
circle2.draw()


3️⃣ Composite (Компоновщик):

Составляет объекты в древовидные структуры для представления иерархий "часть-целое". Позволяет клиентам одинаково обращаться как с отдельными объектами, так и с группами объектов.

Организация структуры компании, где у нас есть как сотрудники, так и отделы.

      class Employee:
def __init__(self, name, position):
self.name = name
self.position = position
self.subordinates = []

def add(self, employee):
self.subordinates.append(employee)

def remove(self, employee):
self.subordinates.remove(employee)

def display(self, indent=0):
print(" " * indent + f"{self.position}: {self.name}")
for subordinate in self.subordinates:
subordinate.display(indent + 2)

ceo = Employee("John", "CEO")
head_sales = Employee("Robert", "Head of Sales")
sales_exec1 = Employee("Laura", "Sales Executive")
sales_exec2 = Employee("Bob", "Sales Executive")

ceo.add(head_sales)
head_sales.add(sales_exec1)
head_sales.add(sales_exec2)

ceo.display()

Структурные паттерны проектирования помогают организовать классы и объекты в крупные структуры, повышая гибкость и расширяемость системы.

🔥 ТОП ВОПРОСОВ С СОБЕСОВ

🔒 База собесов | 🔒 База тестовых
Please open Telegram to view this post
VIEW IN TELEGRAM
👍102🔥2
📌 Что такое паттерн Адаптер (Adapter) ?

💬 Спросят с вероятностью 3%

Паттерн "Адаптер" (Adapter) — это структурный паттерн проектирования, который позволяет объектам с несовместимыми интерфейсами работать вместе. Он служит посредником, преобразуя интерфейс одного класса в интерфейс, который ожидает клиентский код.

😜 Зачем нужен данный паттерн?

1️⃣ Совместимость интерфейсов: Позволяет интегрировать классы с несовместимыми интерфейсами, не изменяя их.

2️⃣ Повторное использование: Упрощает повторное использование существующих классов, предоставляя требуемый интерфейс.

3️⃣ Упрощение кода: Упрощает клиентский код, устраняя необходимость изменений при интеграции новых классов.

🤔 Как работает данный паттерн?

Паттерн включает следующие компоненты:

Целевой интерфейс (Target): Интерфейс, который ожидает клиентский код.

Адаптируемый класс (Adaptee): Класс с несовместимым интерфейсом, который нужно адаптировать.

Адаптер (Adapter): Класс, который преобразует интерфейс Adaptee в интерфейс Target.

# Целевой интерфейс (Target)
class PrinterInterface:
def print(self, text):
pass

# Адаптируемый класс (Adaptee)
class OldPrinter:
def print_old(self, text):
print(f"OldPrinter: {text}")

# Адаптер (Adapter)
class PrinterAdapter(PrinterInterface):
def __init__(self, old_printer):
self.old_printer = old_printer

def print(self, text):
self.old_printer.print_old(text)

# Клиентский код
def client_code(printer: PrinterInterface):
printer.print("Hello, world!")

# Использование
old_printer = OldPrinter()
adapter = PrinterAdapter(old_printer)
client_code(adapter)


Преимущества:

1️⃣ Повышенная совместимость: Позволяет работать с классами, которые иначе были бы несовместимыми.

2️⃣ Упрощение интеграции: Легко интегрировать старые классы с новым кодом без изменения исходных классов.

3️⃣ Поддержка существующего кода: Минимизирует изменения в клиентском коде.

Недостатки:

1️⃣ Дополнительная сложность: Введение адаптера добавляет новый слой абстракции, что может усложнить структуру кода.

2️⃣ Ограниченная производительность: Использование адаптера может в некоторых случаях влиять на производительность из-за дополнительного уровня косвенности.

🤔 Виды:

1️⃣ Класс-адаптер (Class Adapter):

Реализуется через наследование.

Преобразует интерфейс с помощью множественного наследования.

Ограничение: Работает только с адаптируемым классом и его подклассами.

2️⃣ Объект-адаптер (Object Adapter):

Реализуется через композицию.

Преобразует интерфейс, делегируя вызовы методам адаптируемого объекта.

Более гибкий, так как может работать с любыми классами, поддерживающими целевой интерфейс.

Класс-адаптер:
class OldPrinter:
def print_old(self, text):
print(f"OldPrinter: {text}")

class PrinterAdapter(OldPrinter, PrinterInterface):
def print(self, text):
self.print_old(text)

# Использование
adapter = PrinterAdapter()
client_code(adapter)


Объект-адаптер:
class PrinterAdapter(PrinterInterface):
def __init__(self, old_printer):
self.old_printer = old_printer

def print(self, text):
self.old_printer.print_old(text)

# Использование
old_printer = OldPrinter()
adapter = PrinterAdapter(old_printer)
client_code(adapter)


Паттерн "Адаптер" является мощным инструментом для интеграции старых систем с новыми требованиями, обеспечивая гибкость и повторное использование существующих классов без изменения их исходного кода.

🔥 ТОП ВОПРОСОВ С СОБЕСОВ

🔒 База собесов | 🔒 База тестовых
Please open Telegram to view this post
VIEW IN TELEGRAM
👍122
📌 Что такое паттерн Мост (Bridge) ?

💬 Спросят с вероятностью 3%

Паттерн "Мост" (Bridge) — это структурный паттерн проектирования, который разделяет абстракцию и её реализацию так, чтобы они могли изменяться независимо друг от друга. Он используется для разделения сложных систем на части, которые можно развивать, изменять и использовать независимо.

🤔 Зачем нужен данный паттерн?

1️⃣ Разделение ответственности: Позволяет разделить абстрактную часть системы (например, интерфейс) и конкретную реализацию.

2️⃣ Упрощение изменений: Изменения в абстракции или реализации не требуют изменений в другой части.

3️⃣ Гибкость и расширяемость: Упрощает добавление новых абстракций и реализаций без изменения существующего кода.

🤔 Как работает данный паттерн?

Паттерн включает следующие компоненты:

Абстракция (Abstraction): Определяет интерфейс и содержит ссылку на объект реализации.

Расширенная абстракция (Refined Abstraction): Расширяет интерфейс абстракции.

Интерфейс реализации (Implementor): Определяет интерфейс для всех реализаций.

Конкретная реализация (Concrete Implementor): Реализует интерфейс реализации.

from abc import ABC, abstractmethod

# Интерфейс реализации
class DrawingAPI(ABC):
@abstractmethod
def draw_circle(self, x, y, radius):
pass

# Конкретные реализации
class DrawingAPI1(DrawingAPI):
def draw_circle(self, x, y, radius):
print(f"API1.circle at {x}:{y} radius {radius}")

class DrawingAPI2(DrawingAPI):
def draw_circle(self, x, y, radius):
print(f"API2.circle at {x}:{y} radius {radius}")

# Абстракция
class Shape(ABC):
def __init__(self, drawing_api):
self.drawing_api = drawing_api

@abstractmethod
def draw(self):
pass

@abstractmethod
def resize(self, factor):
pass

# Расширенная абстракция
class CircleShape(Shape):
def __init__(self, x, y, radius, drawing_api):
super().__init__(drawing_api)
self.x = x
self.y = y
self.radius = radius

def draw(self):
self.drawing_api.draw_circle(self.x, self.y, self.radius)

def resize(self, factor):
self.radius *= factor

# Использование
circle1 = CircleShape(1, 2, 3, DrawingAPI1())
circle2 = CircleShape(5, 7, 11, DrawingAPI2())

circle1.draw()
circle2.draw()

circle1.resize(2)
circle1.draw()


Преимущества:

1️⃣ Разделение кода: Абстракция и реализация могут изменяться независимо.

2️⃣ Уменьшение связности: Уменьшает зависимость между абстракцией и реализацией.

3️⃣ Гибкость: Легко добавлять новые абстракции и реализации.

Недостатки:

1️⃣ Сложность структуры: Увеличение количества классов и усложнение структуры кода.

2️⃣ Дополнительный уровень косвенности: Может затруднить понимание кода из-за дополнительных уровней абстракции.

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

Когда нужно разделить монолитный класс с несколькими вариациями на иерархии классов абстракции и реализации.

Когда абстракции и реализации должны изменяться независимо друг от друга.

Когда нужно избежать жесткой привязки абстракции к реализации.

Паттерн "Мост" обеспечивает гибкость в проектировании сложных систем, разделяя их на независимые части, что облегчает их развитие и поддержку.

🔥 ТОП ВОПРОСОВ С СОБЕСОВ

🔒 База собесов | 🔒 База тестовых
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5
📌 Что такое паттерн Компоновщик (Composite) ?

💬 Спросят с вероятностью 3%

Паттерн "Компоновщик" (Composite) — это структурный паттерн проектирования, который позволяет сгруппировать объекты в древовидные структуры для представления иерархий "часть-целое". Этот паттерн позволяет клиенту одинаково работать как с отдельными объектами, так и с группами объектов.

🤔 Зачем нужен данный паттерн?

1️⃣ Упрощение клиентского кода: Клиентский код может работать с объектами и их контейнерами одинаково, без необходимости в различении их типов.

2️⃣ Гибкость структуры: Позволяет создавать сложные иерархии объектов динамически.

3️⃣ Повторное использование кода: Легче добавлять новые типы компонентов, не меняя существующий код.

🤔 Как работает данный паттерн?

Паттерн включает следующие компоненты:

Компонент (Component): Определяет общий интерфейс для всех объектов в композиции.

Лист (Leaf): Представляет отдельные объекты, которые не могут иметь подкомпонентов.

Контейнер (Composite): Представляет объекты, которые могут содержать другие компоненты (листы или контейнеры).

from abc import ABC, abstractmethod

# Компонент
class Employee(ABC):
@abstractmethod
def show_details(self):
pass

# Лист
class Developer(Employee):
def __init__(self, name, position):
self.name = name
self.position = position

def show_details(self):
print(f"{self.position}: {self.name}")

class Designer(Employee):
def __init__(self, name, position):
self.name = name
self.position = position

def show_details(self):
print(f"{self.position}: {self.name}")

# Контейнер
class Organization(Employee):
def __init__(self):
self.employees = []

def add(self, employee):
self.employees.append(employee)

def remove(self, employee):
self.employees.remove(employee)

def show_details(self):
for employee in self.employees:
employee.show_details()

# Использование
dev1 = Developer("John Doe", "Senior Developer")
dev2 = Developer("Jane Smith", "Junior Developer")
designer = Designer("Emily Davis", "Senior Designer")

org = Organization()
org.add(dev1)
org.add(dev2)
org.add(designer)

org.show_details()


Преимущества:

1️⃣ Единообразие: Позволяет клиентскому коду работать с индивидуальными объектами и их контейнерами одинаково.

2️⃣ Гибкость: Легко добавлять новые компоненты и контейнеры.

3️⃣ Простота добавления новых элементов: Новые типы компонентов можно добавлять, не изменяя существующий код.

Недостатки:

1️⃣ Сложность управления: Может быть сложно управлять, если структура становится слишком глубокой или разветвленной.

2️⃣ Трудность реализации: Реализация может быть сложной, особенно когда требуется поддерживать разные виды операций над компонентами.

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

Когда требуется представлять иерархические структуры объектов.

Когда нужно, чтобы клиентский код одинаково работал с отдельными объектами и их контейнерами.

Когда нужно упростить работу с объектами, представляющими части целого.

Паттерн "Компоновщик" является мощным инструментом для работы с древовидными структурами данных, позволяя легко манипулировать и управлять как отдельными объектами, так и их группами.

🔥 ТОП ВОПРОСОВ С СОБЕСОВ

🔒 База собесов | 🔒 База тестовых
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
📌 Что такое паттерн Фасад (Facade) ?

💬 Спросят с вероятностью 3%

Паттерн "Фасад" (Facade) — это структурный паттерн проектирования, который предоставляет унифицированный интерфейс для взаимодействия с набором интерфейсов в подсистеме. Фасад определяет высокоуровневый интерфейс, упрощающий работу с более сложной подсистемой.

🤔 Зачем нужен данный паттерн?

1️⃣ Упрощение использования подсистемы: Позволяет клиентам взаимодействовать с подсистемой через простой и понятный интерфейс.

2️⃣ Сокрытие сложности: Скрывает детали реализации и организацию сложной подсистемы от клиентов.

3️⃣ Снижение зависимости: Уменьшает количество зависимостей между клиентами и подсистемой, упрощая поддержку и изменение системы.

🤔 Как работает данный паттерн?

Паттерн включает следующие компоненты:

Фасад (Facade): Класс, предоставляющий упрощенный интерфейс для взаимодействия с подсистемой.

Подсистема (Subsystem): Один или несколько классов, выполняющих сложную работу. Подсистема не знает о существовании фасада и работает автономно.

class Amplifier:
def on(self):
print("Amplifier on")

def set_volume(self, volume):
print(f"Amplifier volume set to {volume}")

def off(self):
print("Amplifier off")

class DVDPlayer:
def on(self):
print("DVD Player on")

def play(self, movie):
print(f"Playing movie: {movie}")

def stop(self):
print("DVD Player stopped")

def off(self):
print("DVD Player off")

class Projector:
def on(self):
print("Projector on")

def set_input(self, input):
print(f"Projector input set to {input}")

def off(self):
print("Projector off")

# Фасад
class HomeTheaterFacade:
def __init__(self, amp, dvd, projector):
self.amp = amp
self.dvd = dvd
self.projector = projector

def watch_movie(self, movie):
print("Get ready to watch a movie...")
self.amp.on()
self.amp.set_volume(5)
self.dvd.on()
self.dvd.play(movie)
self.projector.on()
self.projector.set_input("DVD")

def end_movie(self):
print("Shutting movie theater down...")
self.amp.off()
self.dvd.stop()
self.dvd.off()
self.projector.off()

# Использование
amp = Amplifier()
dvd = DVDPlayer()
projector = Projector()

home_theater = HomeTheaterFacade(amp, dvd, projector)
home_theater.watch_movie("Inception")
home_theater.end_movie()


Преимущества:

1️⃣ Упрощение использования: Предоставляет простой интерфейс для сложной подсистемы.

2️⃣ Сокрытие деталей реализации: Скрывает внутреннюю структуру подсистемы, делая её использование проще и понятнее.

3️⃣ Снижение зависимости: Уменьшает количество зависимостей между клиентами и подсистемой.

Недостатки:

1️⃣ Ограниченная функциональность: Может ограничивать функциональность, предоставляемую подсистемой, если фасад предоставляет слишком упрощенный интерфейс.

2️⃣ Дополнительный слой абстракции: Введение фасада добавляет дополнительный слой кода, что может усложнить систему в некоторых случаях.

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

Когда нужно предоставить простой интерфейс для сложной подсистемы.

Когда нужно сократить количество зависимостей между клиентами и подсистемой.

Когда нужно организовать код и уменьшить связность в системе.

Паттерн "Фасад" является полезным инструментом для упрощения взаимодействия с сложными подсистемами, скрывая их внутреннюю сложность и предоставляя удобный интерфейс для клиентов.

🔥 ТОП ВОПРОСОВ С СОБЕСОВ

🔒 База собесов | 🔒 База тестовых
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10
📌 Что такое паттерн Приспособленец (Flyweight) ?

💬 Спросят с вероятностью 3%

Паттерн "Приспособленец" (Flyweight) — это структурный паттерн проектирования, который позволяет эффективно поддерживать большое количество мелких объектов, минимизируя использование памяти. Это достигается путем совместного использования общего состояния объектов, вместо хранения одинаковых данных в каждом объекте.

🤔 Зачем нужен данный паттерн?

1️⃣ Экономия памяти: Позволяет хранить большое количество объектов, используя меньше памяти за счет разделения общего состояния между ними.

2️⃣ Увеличение производительности: Уменьшение затрат на память может также улучшить производительность системы, особенно если создание объектов является дорогостоящей операцией.

🤔 Как работает данный паттерн?

Паттерн "Приспособленец" разделяет состояние объекта на:

Внутреннее состояние (Intrinsic State): Состояние, которое является одинаковым для многих объектов и может быть разделено между ними.

Внешнее состояние (Extrinsic State): Состояние, которое уникально для каждого объекта и передается в методы.

class Flyweight:
def __init__(self, intrinsic_state):
self.intrinsic_state = intrinsic_state

def operation(self, extrinsic_state):
print(f"Flyweight: Intrinsic state = {self.intrinsic_state}, Extrinsic state = {extrinsic_state}")

class FlyweightFactory:
_flyweights = {}

def get_flyweight(self, intrinsic_state):
if intrinsic_state not in self._flyweights:
self._flyweights[intrinsic_state] = Flyweight(intrinsic_state)
return self._flyweights[intrinsic_state]

# Клиентский код
factory = FlyweightFactory()

# Создание и использование приспособленцев
flyweight1 = factory.get_flyweight("Shared State A")
flyweight1.operation("Unique State 1")

flyweight2 = factory.get_flyweight("Shared State B")
flyweight2.operation("Unique State 2")

flyweight3 = factory.get_flyweight("Shared State A")
flyweight3.operation("Unique State 3")

# Проверка совместного использования приспособленцев
print(flyweight1 is flyweight3) # True


Преимущества:

1️⃣ Экономия памяти: Значительно уменьшает количество памяти, необходимое для хранения большого количества объектов.

2️⃣ Увеличение
производительности
: Снижение затрат на создание и хранение объектов может улучшить общую производительность системы.

Недостатки:

1️⃣ Сложность реализации: Требует тщательной разработки для правильного разделения внутреннего и внешнего состояния.

2️⃣ Снижение читабельности кода: Использование внешнего состояния может сделать код менее понятным и трудным для сопровождения.

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

Когда система должна эффективно работать с большим количеством объектов.

Когда значительная часть состояния объектов может быть разделена.

Когда создание объектов является дорогостоящей операцией и использование памяти критично.

Паттерн "Приспособленец" является мощным инструментом для оптимизации использования памяти и повышения производительности в системах, работающих с большим количеством однотипных объектов.

🔥 ТОП ВОПРОСОВ С СОБЕСОВ

🔒 База собесов | 🔒 База тестовых
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7
📌 Что такое паттерн Заместитель (Proxy) ?

💬 Спросят с вероятностью 3%

Паттерн "Заместитель" (Proxy) — это структурный паттерн проектирования, который предоставляет суррогатный или заместительный объект для другого объекта с целью контроля доступа к нему. Заместитель выполняет функции обёртки или посредника, передавая вызовы к реальному объекту и добавляя к ним дополнительную логику.

🤔 Зачем нужен данный паттерн?

1️⃣ Контроль доступа: Позволяет управлять доступом к объекту, добавляя проверки и ограничения.

2️⃣ Ленивая инициализация: Позволяет откладывать создание и инициализацию ресурсоёмких объектов до момента, когда они действительно понадобятся.

3️⃣ Удалённый доступ: Обеспечивает взаимодействие с удалёнными объектами, как будто они локальные.

4️⃣ Логирование и кэширование: Добавляет дополнительные действия, такие как логирование или кэширование, при доступе к объекту.

🤔 Как работает данный паттерн?

Паттерн "Заместитель" включает следующие компоненты:

Реальный субъект (RealSubject): Класс, представляющий реальный объект, к которому требуется контролируемый доступ.

Интерфейс (Subject): Общий интерфейс для реального субъекта и заместителя, позволяющий заместителю подменять реальный объект.

Заместитель (Proxy): Класс, который реализует интерфейс и содержит ссылку на реальный объект. Он перехватывает вызовы к реальному объекту и может добавлять к ним дополнительную логику.

from abc import ABC, abstractmethod

# Интерфейс (Subject)
class Subject(ABC):
@abstractmethod
def request(self):
pass

# Реальный субъект (RealSubject)
class RealSubject(Subject):
def request(self):
print("RealSubject: Handling request.")

# Заместитель (Proxy)
class Proxy(Subject):
def __init__(self, real_subject):
self._real_subject = real_subject

def request(self):
if self.check_access():
self._real_subject.request()
self.log_access()

def check_access(self):
print("Proxy: Checking access prior to firing a real request.")
return True

def log_access(self):
print("Proxy: Logging the time of request.")

# Клиентский код
def client_code(subject: Subject):
subject.request()

# Использование
real_subject = RealSubject()
proxy = Proxy(real_subject)
client_code(proxy)


Преимущества:

1️⃣ Контроль доступа: Позволяет легко управлять доступом к реальному объекту.

2️⃣ Ленивая инициализация: Экономит ресурсы, откладывая создание объектов до необходимости.

3️⃣ Логирование и кэширование: Обеспечивает функциональность без изменения реального объекта.

4️⃣ Удалённый доступ: Упрощает взаимодействие с удалёнными объектами.

Недостатки:

1️⃣ Усложнение кода: Добавляет дополнительные классы и слои абстракции, что может усложнить систему.

2️⃣ Снижение производительности: Введение дополнительных проверок и логики может повлиять на производительность.

🤔 Виды:

1️⃣ Remote Proxy: Управляет взаимодействием с удалённым объектом.

2️⃣ Virtual Proxy: Управляет доступом к ресурсоёмкому объекту, создавая его по требованию.

3️⃣ Protection Proxy: Контролирует доступ к объекту, обеспечивая безопасность.

4️⃣ Smart Proxy: Добавляет дополнительную функциональность при доступе к объекту (например, рефлекторное считывание и запись).

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

Когда нужно контролировать доступ к ресурсоёмкому или удалённому объекту.

Когда требуется добавить дополнительные операции при доступе к объекту.

Когда необходимо обеспечить безопасность и контроль над доступом к объекту.

Паттерн "Заместитель" является мощным инструментом для управления доступом к объектам, добавления логики и улучшения производительности в определённых сценариях.

🔥 ТОП ВОПРОСОВ С СОБЕСОВ

🔒 База собесов | 🔒 База тестовых
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6🔥1
📌 Что такое поведенческие паттерны ?

💬 Спрашивают в 3% собеседований

Поведенческие паттерны (Behavioral Patterns) — это шаблоны проектирования, которые определяют способы взаимодействия объектов и классов, эффективное распределение обязанностей между ними и упрощают коммуникацию. Эти паттерны фокусируются на алгоритмах и потоках управления в системе, обеспечивая гибкость и расширяемость программного кода.

🤔 Основные паттерны

1️⃣ Chain of Responsibility (Цепочка обязанностей):

Позволяет передавать запрос последовательно по цепочке обработчиков, пока один из них не обработает запрос.

Система логирования, где различные уровни логов (информация, предупреждение, ошибка) обрабатываются разными обработчиками.

      class Handler(ABC):
def __init__(self, successor=None):
self._successor = successor

@abstractmethod
def handle(self, request):
pass

class ConcreteHandler1(Handler):
def handle(self, request):
if request == "Condition1":
print("Handled by ConcreteHandler1")
elif self._successor:
self._successor.handle(request)

class ConcreteHandler2(Handler):
def handle(self, request):
if request == "Condition2":
print("Handled by ConcreteHandler2")
elif self._successor:
self._successor.handle(request)

# Использование
handler = ConcreteHandler1(ConcreteHandler2())
handler.handle("Condition2")


2️⃣ Command (Команда):

Инкапсулирует запрос как объект, позволяя параметризовать клиентов с разными запросами, ставить запросы в очередь или записывать их в журнал.

Система меню, где каждый пункт меню представляет команду.

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

class Light:
def on(self):
print("Light is ON")

def off(self):
print("Light is OFF")

class LightOnCommand(Command):
def __init__(self, light):
self._light = light

def execute(self):
self._light.on()

class LightOffCommand(Command):
def __init__(self, light):
self._light = light

def execute(self):
self._light.off()

# Использование
light = Light()
light_on = LightOnCommand(light)
light_off = LightOffCommand(light)

light_on.execute()
light_off.execute()


3️⃣ Iterator (Итератор):

Предоставляет способ последовательного доступа ко всем элементам коллекции без раскрытия её внутреннего представления.

Обход элементов массива или связного списка.

      class Iterator(ABC):
@abstractmethod
def next(self):
pass

@abstractmethod
def has_next(self):
pass

class ConcreteIterator(Iterator):
def __init__(self, collection):
self._collection = collection
self._index = 0

def next(self):
item = self._collection[self._index]
self._index += 1
return item

def has_next(self):
return self._index < len(self._collection)

# Использование
collection = [1, 2, 3, 4]
iterator = ConcreteIterator(collection)

while iterator.has_next():
print(iterator.next())

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

🔥 ТОП ВОПРОСОВ С СОБЕСОВ

🔒 База собесов | 🔒 База тестовых
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
📌 Что такое Цепочка ответственности (Chain of responsobility) ?

💬 Спрашивают в 3% собеседований

Цепочка ответственности (Chain of Responsibility) — это поведенческий паттерн проектирования, который позволяет передавать запросы последовательно по цепочке обработчиков. Каждый обработчик решает, может ли он обработать запрос самостоятельно, либо передает его следующему обработчику в цепочке.

🤔 Зачем нужен данный паттерн?

1️⃣ Изоляция отправителя запроса от его получателей: Отправитель запроса не не знает, какой именно обработчик его обработает.

2️⃣ Гибкость в распределении обязанностей: Легко менять цепочку обработчиков и их последовательность.

3️⃣ Уменьшение зависимости между объектами: Позволяет избежать жёсткой привязки отправителей к конкретным обработчикам.

🤔 Как работает данный паттерн?

Паттерн включает следующие компоненты:

Обработчик (Handler): Интерфейс или абстрактный класс, определяющий метод для обработки запроса и ссылку на следующий обработчик в цепочке.

Конкретные обработчики (ConcreteHandler): Классы, реализующие интерфейс обработчика. Каждый обработчик решает, может ли он обработать запрос, либо передает его следующему обработчику.

Клиент (Client): Отправляет запрос первому обработчику в цепочке.

from abc import ABC, abstractmethod

# Абстрактный обработчик
class Handler(ABC):
def __init__(self, successor=None):
self._successor = successor

@abstractmethod
def handle(self, request):
pass

# Конкретный обработчик 1
class ConcreteHandler1(Handler):
def handle(self, request):
if request == "Condition1":
print("Handled by ConcreteHandler1")
elif self._successor:
self._successor.handle(request)

# Конкретный обработчик 2
class ConcreteHandler2(Handler):
def handle(self, request):
if request == "Condition2":
print("Handled by ConcreteHandler2")
elif self._successor:
self._successor.handle(request)

# Клиентский код
def client_code(handler, request):
handler.handle(request)

# Создание цепочки обработчиков
handler1 = ConcreteHandler1()
handler2 = ConcreteHandler2(handler1)

# Использование
client_code(handler2, "Condition1") # Handled by ConcreteHandler1
client_code(handler2, "Condition2") # Handled by ConcreteHandler2
client_code(handler2, "Condition3") # Ничего не происходит, так как запрос не обработан


🤔 Преимущества:

1️⃣ Гибкость в распределении обязанностей: Легко изменять цепочку обработчиков.

2️⃣ Изоляция отправителя запроса от его получателей: Отправитель запроса не знает, какой именно обработчик его обработает.

3️⃣ Уменьшение зависимости между объектами: Меньше жёстких привязок между отправителями и получателями запросов.

🤔 Недостатки:

1️⃣ Неопределенность обработки: Запрос может остаться необработанным, если ни один из обработчиков не сможет его обработать.

2️⃣ Сложность отладки: Из-за передачи запроса по цепочке может быть сложно определить, где именно он был обработан или отклонен.

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

Когда необходимо передавать запросы нескольким объектам без жесткой привязки к конкретным обработчикам.

Когда набор обработчиков и их порядок должен легко изменяться.

Когда необходимо избежать жёсткой привязки отправителей запросов к их получателям.

Паттерн "Цепочка ответственности" является мощным инструментом для гибкого и динамичного распределения обязанностей по обработке запросов в системе.

🔥 ТОП ВОПРОСОВ С СОБЕСОВ

🔒 База собесов | 🔒 База тестовых
Please open Telegram to view this post
VIEW IN TELEGRAM
👍41
🤔 Какой модуль используется для работы с многопоточностью в Python?
Anonymous Quiz
30%
asyncio
20%
multiprocessing
49%
threading
2%
concurrent
📌 Что такое паттерн Команда (Command) ?

💬 Спрашивают в 3% собеседований

Паттерн "Команда" (Command) — это поведенческий паттерн проектирования, который превращает запросы в объекты, позволяя передавать их как аргументы при вызове методов, ставить запросы в очередь, логировать их и поддерживать отмену операций.

🤔 Зачем нужен данный паттерн?

1️⃣ Инкапсуляция запросов: Позволяет инкапсулировать запросы в виде объектов.

2️⃣ Разделение ответственности: Отделяет отправителя запроса от объекта, выполняющего запрос.

3️⃣ Логирование и отмена: Упрощает реализацию логирования, очереди запросов и отмены операций.

4️⃣ Параметризация объектов: Позволяет параметризовать объекты с операциями.

🤔 Как работает данный паттерн?

Паттерн включает следующие компоненты:

Команда (Command): Интерфейс с методом execute.

Конкретные команды (ConcreteCommand): Реализуют интерфейс команды, инкапсулируя действия для конкретного запроса.

Получатель (Receiver): Объект, который выполняет действие по запросу.

Отправитель (Invoker): Объект, который инициирует выполнение команды.

Клиент (Client): Создаёт объекты команд и связывает их с получателями.

from abc import ABC, abstractmethod

# Интерфейс команды
class Command(ABC):
@abstractmethod
def execute(self):
pass

# Получатель
class Light:
def on(self):
print("Light is ON")

def off(self):
print("Light is OFF")

# Конкретная команда включения света
class LightOnCommand(Command):
def __init__(self, light):
self._light = light

def execute(self):
self._light.on()

# Конкретная команда выключения света
class LightOffCommand(Command):
def __init__(self, light):
self._light = light

def execute(self):
self._light.off()

# Отправитель
class RemoteControl:
def __init__(self):
self._commands = {}

def set_command(self, button, command):
self._commands[button] = command

def press_button(self, button):
if button in self._commands:
self._commands[button].execute()
else:
print("No command assigned to this button")

# Клиентский код
light = Light()
light_on = LightOnCommand(light)
light_off = LightOffCommand(light)

remote = RemoteControl()
remote.set_command("ON", light_on)
remote.set_command("OFF", light_off)

remote.press_button("ON") # Light is ON
remote.press_button("OFF") # Light is OFF
remote.press_button("UNASSIGNED") # No command assigned to this button


🤔 Преимущества:

1️⃣ Инкапсуляция запросов: Позволяет инкапсулировать действия в объекты команд.

2️⃣ Поддержка отмены и логирования: Упрощает реализацию отмены операций и логирования.

3️⃣ Гибкость и расширяемость: Легко добавлять новые команды без изменения существующего кода.

4️⃣ Разделение ответственности: Разделяет ответственность между отправителем и получателем.

🤔 Недостатки:

1️⃣ Усложнение кода: Добавление множества классов команд может усложнить код.

2️⃣ Требует дополнительных ресурсов: Создание объектов команд может потребовать дополнительных ресурсов.

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

Когда нужно параметризовать объекты выполняемыми действиями.

Когда требуется логирование, отмена и повтор запросов.

Когда нужно передавать операции в очереди или как аргументы при вызове методов.

Когда нужно разделить ответственность между отправителем запроса и объектом, выполняющим запрос.

Паттерн "Команда" является мощным инструментом для управления действиями и их инкапсуляции, обеспечивая гибкость и расширяемость системы.

🔥 ТОП ВОПРОСОВ С СОБЕСОВ

🔒 База собесов | 🔒 База тестовых
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3👀1
📌 Что такое паттерн Интерпретатор (Interpreter) ?

💬 Спрашивают в 3% собеседований

Паттерн "Интерпретатор" (Interpreter) — это поведенческий паттерн проектирования, который предоставляет способ определить грамматику для определенного языка и интерпретировать предложения на этом языке. Паттерн используется для анализа и выполнения структурированных текстов, таких как математические выражения, команды или сценарии.

🤔 Зачем нужен данный паттерн?

1️⃣ Анализ и выполнение текстов: Позволяет анализировать и выполнять предложения на специальном языке.

2️⃣ Упрощение грамматики: Разделяет грамматику языка и её интерпретацию, что упрощает понимание и изменение правил языка.

3️⃣ Расширяемость: Легко добавлять новые правила и расширять язык.

🤔 Как работает данный паттерн?

Паттерн включает следующие компоненты:

Контекст (Context): Содержит информацию, глобальную для всех интерпретаторов.

Абстрактное выражение (AbstractExpression): Интерфейс или абстрактный класс для всех выражений.

Конкретные выражения (TerminalExpression и NonTerminalExpression): Классы, реализующие конкретные правила грамматики.

Клиент (Client): Построит и использует объектную структуру абстрактного синтаксического дерева.

from abc import ABC, abstractmethod

# Контекст (необязательный компонент)
class Context:
pass

# Абстрактное выражение
class Expression(ABC):
@abstractmethod
def interpret(self, context):
pass

# Терминальное выражение (число)
class Number(Expression):
def __init__(self, value):
self.value = value

def interpret(self, context):
return self.value

# Нетерминальное выражение (сложение)
class Add(Expression):
def __init__(self, left, right):
self.left = left
self.right = right

def interpret(self, context):
return self.left.interpret(context) + self.right.interpret(context)

# Нетерминальное выражение (вычитание)
class Subtract(Expression):
def __init__(self, left, right):
self.left = left
self.right = right

def interpret(self, context):
return self.left.interpret(context) - self.right.interpret(context)

# Клиентский код
def main():
# Построение выражения: 1 + 2 - 3
expression = Subtract(Add(Number(1), Number(2)), Number(3))
context = Context() # Контекст может использоваться для передачи информации
result = expression.interpret(context)
print(result) # 0

if __name__ == "__main__":
main()


🤔 Преимущества:

1️⃣ Простота добавления новых правил: Легко добавлять новые грамматические правила и расширять язык.

2️⃣ Четкая структура: Грамматика и интерпретация языка разделены, что упрощает понимание и изменение.

🤔 Недостатки:

1️⃣ Ограниченная производительность: Может быть неэффективным для сложных или очень больших грамматик.

2️⃣ Сложность поддержки: Поддержка сложных грамматик может стать трудной из-за большого числа классов.

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

Когда есть необходимость интерпретировать и выполнять предложения на определенном языке.

Когда грамматика языка относительно проста и стабильна.

Когда нужно часто добавлять новые грамматические правила.

Паттерн "Интерпретатор" является мощным инструментом для определения и интерпретации грамматик, позволяя легко анализировать и выполнять структурированные тексты.

🔥 ТОП ВОПРОСОВ С СОБЕСОВ

🔒 База собесов | 🔒 База тестовых
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5🤔3
📌 Что такое паттерн Посредник (Mediator) ?

💬 Спрашивают в 3% собеседований

Паттерн "Посредник" (Mediator) — это поведенческий паттерн проектирования, который позволяет уменьшить зависимости между объектами, упрощая их взаимодействие. Посредник инкапсулирует способ взаимодействия множества объектов, предотвращая их прямые ссылки друг на друга, что уменьшает связность системы и улучшает её модульность.

🤔 Зачем нужен данный паттерн?

1️⃣ Уменьшение связности: Обеспечивает слабую связанность между взаимодействующими объектами, что упрощает изменение и повторное использование классов.

2️⃣ Упрощение взаимодействий: Объекты взаимодействуют через посредника, что упрощает управление их взаимодействиями.

3️⃣ Централизованный контроль: Все взаимодействия проходят через посредника, что облегчает отладку и тестирование системы.

🤔 Как работает данный паттерн?

Паттерн включает следующие компоненты:

Посредник (Mediator): Интерфейс, определяющий методы для взаимодействия с коллегами.

Конкретный посредник (ConcreteMediator): Реализует методы взаимодействия, определённые в интерфейсе посредника.

Коллеги (Colleague): Классы, которые обмениваются информацией через посредника. Каждый коллега знает о посреднике, но не знает о других коллегах.

from abc import ABC, abstractmethod

# Посредник
class Mediator(ABC):
@abstractmethod
def notify(self, sender, event):
pass

# Конкретный посредник
class ConcreteMediator(Mediator):
def __init__(self):
self.button = None
self.textbox = None

def set_button(self, button):
self.button = button

def set_textbox(self, textbox):
self.textbox = textbox

def notify(self, sender, event):
if event == "button_clicked":
self.textbox.enable()
elif event == "textbox_filled":
self.button.enable()

# Коллеги
class Button:
def __init__(self, mediator):
self.mediator = mediator
self.enabled = False

def click(self):
print("Button clicked.")
self.mediator.notify(self, "button_clicked")

def enable(self):
self.enabled = True
print("Button enabled.")

class TextBox:
def __init__(self, mediator):
self.mediator = mediator
self.enabled = False

def fill(self):
print("TextBox filled.")
self.mediator.notify(self, "textbox_filled")

def enable(self):
self.enabled = True
print("TextBox enabled.")

# Клиентский код
mediator = ConcreteMediator()
button = Button(mediator)
textbox = TextBox(mediator)

mediator.set_button(button)
mediator.set_textbox(textbox)

button.click() # Button clicked. TextBox enabled.
textbox.fill() # TextBox filled. Button enabled.


🤔 Преимущества:

1️⃣ Уменьшение связности: Упрощает изменение и повторное использование объектов, уменьшает количество прямых зависимостей между ними.

2️⃣ Упрощение взаимодействий: Все взаимодействия централизованы, что упрощает управление ими.

3️⃣ Централизованный контроль: Облегчает отладку и тестирование, так как все взаимодействия проходят через один объект.

🤔 Недостатки:

1️⃣ Централизация логики: Посредник может стать слишком сложным и трудным для поддержки, если будет обрабатывать слишком много логики.

2️⃣ Ограниченная масштабируемость: Централизация может стать узким местом, особенно в крупных системах с множеством взаимодействий.

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

Когда нужно уменьшить связность между множеством взаимодействующих объектов.

Когда нужно централизовать сложные взаимодействия между объектами.

Когда изменения в одном объекте должны привести к изменениям в других, без необходимости явно связывать их.

Паттерн "Посредник" является мощным инструментом для управления взаимодействиями в системе, улучшая её модульность и уменьшая сложность.

🔥 ТОП ВОПРОСОВ С СОБЕСОВ

🔒 База собесов | 🔒 База тестовых
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6🔥2
📌 Что такое хранитель (Memento) ?

💬 Спрашивают в 3% собеседований

Паттерн "Хранитель" (Memento) — это поведенческий паттерн проектирования, который позволяет сохранять и восстанавливать состояние объекта, не раскрывая его внутреннюю структуру. Это полезно для реализации функций отмены операций, восстановления предыдущих состояний и создания контрольных точек.

🤔 Зачем нужен данный паттерн?

1️⃣ Отмена и повтор операций: Позволяет легко отменять изменения и возвращаться к предыдущим состояниям.

2️⃣ Сохранение состояния: Позволяет сохранять состояния объектов в определённые моменты времени.

3️⃣ Инкапсуляция состояния: Хранит внутреннее состояние объекта, не нарушая его инкапсуляции.

🤔 Как работает данный паттерн?

Паттерн включает следующие компоненты:

Хранитель (Memento): Объект, который сохраняет состояние другого объекта.

Создатель (Originator): Объект, чьё состояние сохраняется и восстанавливается.

Опекун (Caretaker): Объект, который отвечает за хранение хранителей и, при необходимости, предоставляет их создателю для восстановления состояния.

# Хранитель
class Memento:
def __init__(self, state):
self._state = state

def get_state(self):
return self._state

# Создатель
class TextEditor:
def __init__(self):
self._state = ""

def type(self, text):
self._state += text

def save(self):
return Memento(self._state)

def restore(self, memento):
self._state = memento.get_state()

def get_state(self):
return self._state

# Опекун
class History:
def __init__(self):
self._mementos = []

def save(self, memento):
self._mementos.append(memento)

def undo(self):
if not self._mementos:
return None
return self._mementos.pop()

# Клиентский код
editor = TextEditor()
history = History()

# Пользователь вводит текст
editor.type("Hello, ")
editor.type("world!")
print(editor.get_state()) # Hello, world!

# Сохранение состояния
history.save(editor.save())

# Продолжение ввода текста
editor.type(" How are you?")
print(editor.get_state()) # Hello, world! How are you?

# Восстановление состояния
editor.restore(history.undo())
print(editor.get_state()) # Hello, world!


🤔 Преимущества:

1️⃣ Отмена и восстановление: Легко реализовать функции отмены и восстановления.

2️⃣ Инкапсуляция состояния: Состояние сохраняется и восстанавливается без нарушения инкапсуляции.

3️⃣ Упрощение управления состоянием: Позволяет создавать контрольные точки состояния объекта.

🤔 Недостатки:

1️⃣ Увеличение использования памяти: Сохранение состояния может потребовать значительных ресурсов, особенно для больших объектов.

2️⃣ Сложность управления: В сложных системах может быть трудно управлять множеством состояний и хранителей.

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

Когда необходимо реализовать функции отмены и восстановления.

Когда нужно сохранять состояние объекта в определённые моменты времени.

Когда важно сохранять состояние объекта, не нарушая его инкапсуляции.

Паттерн "Хранитель" является мощным инструментом для управления состоянием объектов, предоставляя возможность сохранять и восстанавливать состояния без раскрытия внутренней структуры объекта.

🔥 ТОП ВОПРОСОВ С СОБЕСОВ

🔒 База собесов | 🔒 База тестовых
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8🔥1
📌 Что такое Наблюдатель (Observer) ?

💬 Спрашивают в 3% собеседований

Паттерн "Наблюдатель" (Observer) — это поведенческий паттерн проектирования, который определяет зависимость "один ко многим" между объектами. Когда состояние одного объекта изменяется, все его зависимые объекты автоматически оповещаются и обновляются. Этот паттерн позволяет объектам подписываться на события, происходящие в другом объекте.

🤔 Зачем нужен данный паттерн?

1️⃣ Обновление состояния: Автоматически оповещает зависимые объекты о изменениях в объекте-наблюдаемом.

2️⃣ Разделение обязанностей: Позволяет разделить логику оповещения и обновления состояния между объектами.

3️⃣ Гибкость и расширяемость: Упрощает добавление новых наблюдателей и изменение их поведения без изменения кода объекта-наблюдаемого.

🤔 Как работает данный паттерн?

Паттерн включает следующие компоненты:

Субъект (Subject): Интерфейс или абстрактный класс, определяющий методы для добавления, удаления и оповещения наблюдателей.

Конкретный субъект (ConcreteSubject): Реализация субъекта, хранящая состояние и оповещающая наблюдателей об изменениях.

Наблюдатель (Observer): Интерфейс или абстрактный класс, определяющий метод для обновления состояния в ответ на оповещения.

Конкретный наблюдатель (ConcreteObserver): Реализация наблюдателя, обновляющая своё состояние в ответ на изменения субъекта.

from abc import ABC, abstractmethod

# Интерфейс наблюдателя
class Observer(ABC):
@abstractmethod
def update(self, temperature):
pass

# Конкретный наблюдатель
class TemperatureDisplay(Observer):
def update(self, temperature):
print(f"Temperature Display: Temperature updated to {temperature}°C")

class TemperatureAlert(Observer):
def update(self, temperature):
if temperature > 30:
print("Temperature Alert: Temperature is too high!")

# Субъект
class WeatherStation:
def __init__(self):
self._observers = []
self._temperature = None

def add_observer(self, observer):
self._observers.append(observer)

def remove_observer(self, observer):
self._observers.remove(observer)

def set_temperature(self, temperature):
self._temperature = temperature
self.notify_observers()

def notify_observers(self):
for observer in self._observers:
observer.update(self._temperature)

# Клиентский код
weather_station = WeatherStation()
display = TemperatureDisplay()
alert = TemperatureAlert()

weather_station.add_observer(display)
weather_station.add_observer(alert)

weather_station.set_temperature(25) # Temperature Display: Temperature updated to 25°C
weather_station.set_temperature(35) # Temperature Display: Temperature updated to 35°C
# Temperature Alert: Temperature is too high!


🤔 Преимущества:

1️⃣ Автоматическое оповещение: Автоматически обновляет наблюдателей при изменении состояния субъекта.

2️⃣ Разделение обязанностей: Субъект не знает о конкретных наблюдателях и их логике.

3️⃣ Гибкость и расширяемость: Легко добавлять новых наблюдателей и изменять их поведение.

🤔 Недостатки:

1️⃣ Порядок уведомления: Порядок оповещения наблюдателей может быть важен и требует управления.

2️⃣ Потенциальные утечки памяти: Неудаленные наблюдатели могут привести к утечкам памяти.

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

Когда изменение состояния одного объекта должно приводить к изменению других объектов.

Когда необходимо централизованное оповещение об изменениях состояния.

Когда нужно минимизировать связи между субъектом и наблюдателями.

Паттерн "Наблюдатель" является мощным инструментом для управления зависимостями и оповещением в системе, упрощая взаимодействие между объектами и улучшая модульность кода.

🔥 ТОП ВОПРОСОВ С СОБЕСОВ

🔒 База собесов | 🔒 База тестовых
Please open Telegram to view this post
VIEW IN TELEGRAM
👍51
📌 Что такое паттерн Состояние (State) ?

💬 Спрашивают в 3% собеседований

Паттерн "Состояние" (State) — это поведенческий паттерн проектирования, который позволяет объекту изменять свое поведение в зависимости от его внутреннего состояния. Внешне это выглядит так, как будто объект изменил свой класс. Этот паттерн особенно полезен, когда объект может находиться в нескольких состояниях, каждое из которых определяет его поведение.

🤔 Зачем нужен данный паттерн?

1️⃣ Управление состояниями: Позволяет управлять сложными состояниями объекта, организуя код более структурировано.

2️⃣ Изолирование состояний: Разделяет код, относящийся к разным состояниям, что упрощает его поддержку и модификацию.

3️⃣ Изменение поведения во время выполнения: Объект может динамически изменять своё поведение в зависимости от текущего состояния.

🤔 Как работает данный паттерн?

Паттерн включает следующие компоненты:

Контекст (Context): Объект, который содержит ссылку на текущий объект состояния и делегирует ему выполнение поведения.

Состояние (State): Интерфейс или абстрактный класс, определяющий общие методы для всех конкретных состояний.

Конкретные состояния (ConcreteState): Классы, реализующие конкретное поведение в зависимости от состояния.

from abc import ABC, abstractmethod

# Интерфейс состояния
class State(ABC):
@abstractmethod
def insert_coin(self, context):
pass

@abstractmethod
def press_button(self, context):
pass

@abstractmethod
def dispense(self, context):
pass

# Конкретные состояния
class NoCoinState(State):
def insert_coin(self, context):
print("Coin inserted.")
context.state = context.has_coin_state

def press_button(self, context):
print("Insert coin first.")

def dispense(self, context):
print("Insert coin first.")

class HasCoinState(State):
def insert_coin(self, context):
print("Coin already inserted.")

def press_button(self, context):
print("Button pressed.")
context.state = context.sold_state

def dispense(self, context):
print("Press button to dispense.")

class SoldState(State):
def insert_coin(self, context):
print("Wait! Dispensing in progress.")

def press_button(self, context):
print("Wait! Dispensing in progress.")

def dispense(self, context):
print("Ticket dispensed.")
context.state = context.no_coin_state

# Контекст
class TicketMachine:
def __init__(self):
self.no_coin_state = NoCoinState()
self.has_coin_state = HasCoinState()
self.sold_state = SoldState()
self.state = self.no_coin_state

def insert_coin(self):
self.state.insert_coin(self)

def press_button(self):
self.state.press_button(self)

def dispense(self):
self.state.dispense(self)

# Клиентский код
machine = TicketMachine()

machine.insert_coin() # Coin inserted.
machine.press_button() # Button pressed.
machine.dispense() # Ticket dispensed.

machine.press_button() # Insert coin first.
machine.insert_coin() # Coin inserted.
machine.dispense() # Press button to dispense.
machine.press_button() # Button pressed.
machine.dispense() # Ticket dispensed.


🤔 Преимущества:

1️⃣ Управление состояниями: Упрощает управление сложными состояниями объекта.

2️⃣ Изолирование состояний: Позволяет разделить код, относящийся к разным состояниям.

3️⃣ Динамическое изменение поведения: Объект может динамически изменять своё поведение.

🤔 Недостатки:

1️⃣ Усложнение кода: Добавление большого количества классов состояний может усложнить код.

2️⃣ Повышенные накладные
расходы
: Частые изменения состояния могут привести к дополнительным накладным расходам.

Паттерн "Состояние" является мощным инструментом для управления состояниями объекта и изменением его поведения в зависимости от этих состояний, что упрощает код и улучшает его структуру.

🔥 ТОП ВОПРОСОВ С СОБЕСОВ

🔒 База собесов | 🔒 База тестовых
Please open Telegram to view this post
VIEW IN TELEGRAM
3👍1👀1