Anonymous Quiz
14%
slots автоматически создаёт свойства для каждого атрибута
10%
slots используется для изменения значений атрибутов объекта
71%
slots используется для ограничения допустимых атрибутов объекта и экономии памяти
5%
slots используется для предотвращения создания экземпляров класса
Паттерн Интерпретатор (Interpreter) — это поведенческий паттерн проектирования, который определяет грамматику для представления языка и интерпретатор, использующий эту грамматику для интерпретации предложений на этом языке. Паттерн используется для построения простых языков или для интерпретации конкретного типа выражений.
Помогает формализовать и структурировать правила языка или протокола.
Позволяет создавать интерпретатор для выполнения выражений, написанных на определенном языке.
Обеспечивает легкость добавления новых правил и расширения языка без изменения существующего кода.
from abc import ABC, abstractmethod
# Интерфейс выражения
class Expression(ABC):
@abstractmethod
def interpret(self):
pass
# Конкретное выражение для чисел
class Number(Expression):
def __init__(self, value):
self.value = value
def interpret(self):
return self.value
# Конкретное выражение для сложения
class Add(Expression):
def __init__(self, left: Expression, right: Expression):
self.left = left
self.right = right
def interpret(self):
return self.left.interpret() + self.right.interpret()
# Конкретное выражение для умножения
class Multiply(Expression):
def __init__(self, left: Expression, right: Expression):
self.left = left
self.right = right
def interpret(self):
return self.left.interpret() * self.right.interpret()
# Клиентский код для использования паттерна Интерпретатор
def main():
# Создаем выражение: (5 + 10) * 2
expression = Multiply(
Add(Number(5), Number(10)),
Number(2)
)
result = expression.interpret()
print(f"Result: {result}") # Result: 30
if __name__ == "__main__":
main()
Объявляет метод
interpret
, который должен реализовать каждое конкретное выражение.Классы
Number
, Add
и Multiply
, которые реализуют интерфейс Expression
и определяют интерпретацию чисел, сложения и умножения соответственно.Выражения могут быть составными, например,
Add
и Multiply
могут принимать другие выражения в качестве аргументов.Метод
interpret
вызывается для вычисления значения выражения.Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8❤1
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍26
Паттерн "Мост" (Bridge) является структурным паттерном проектирования, который предназначен для разделения абстракции и реализации так, чтобы они могли изменяться независимо друг от друга. Этот паттерн полезен, когда класс должен работать с различными платформами или когда нужно избежать жесткой связки между абстракцией и ее реализацией.
Он позволяет отделить абстракцию от ее реализации, что упрощает поддержку и расширение системы.
Без применения этого паттерна, если у нас есть несколько вариантов абстракции и несколько вариантов реализации, то нам пришлось бы создавать классы для всех возможных комбинаций, что приводит к взрывному росту количества классов.
Это позволяет изменять и абстракцию, и реализацию независимо друг от друга.
Определяет интерфейс и хранит ссылку на объект Implementor.
Наследует Abstraction и расширяет интерфейс.
Определяет интерфейс для всех реализаций.
Реализует интерфейс Implementor.
Допустим, у нас есть программа для управления различными типами устройств (например, телевизор и радио), которые можно включать и выключать. Мы хотим, чтобы способ управления устройствами мог изменяться независимо от типов устройств.
# Implementor
class Device:
def is_enabled(self):
pass
def enable(self):
pass
def disable(self):
pass
# ConcreteImplementor
class TV(Device):
def __init__(self):
self._on = False
def is_enabled(self):
return self._on
def enable(self):
self._on = True
def disable(self):
self._on = False
class Radio(Device):
def __init__(self):
self._on = False
def is_enabled(self):
return self._on
def enable(self):
self._on = True
def disable(self):
self._on = False
# Abstraction
class RemoteControl:
def __init__(self, device):
self._device = device
def toggle_power(self):
if self._device.is_enabled():
self._device.disable()
else:
self._device.enable()
# RefinedAbstraction
class AdvancedRemoteControl(RemoteControl):
def mute(self):
print("Device is muted.")
# Клиентский код
tv = TV()
remote = RemoteControl(tv)
remote.toggle_power() # Включает TV
radio = Radio()
advanced_remote = AdvancedRemoteControl(radio)
advanced_remote.toggle_power() # Включает Radio
advanced_remote.mute() # Заглушает Radio
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍18🔥9❤2
Паттерн Компоновщик (Composite) — это структурный паттерн проектирования, который позволяет сгруппировать объекты в древовидную структуру для представления иерархии "часть-целое". Этот паттерн используется для работы с объектами как с единичными, так и с составными единицами, предоставляя единый интерфейс для работы с ними.
Основная цель паттерна Компоновщик — упростить работу с иерархическими структурами данных. Он позволяет клиенту обращаться с отдельными объектами и их группами единообразно, что делает код более гибким и упрощает его поддержку.
это базовый элемент без подкомпонентов.
это элемент, который может содержать другие компоненты, включая и листья, и другие компоновщики.
from abc import ABC, abstractmethod
# Абстрактный компонент
class Graphic(ABC):
@abstractmethod
def draw(self):
pass
# Лист
class Circle(Graphic):
def draw(self):
print("Drawing a Circle")
# Компоновщик
class CompositeGraphic(Graphic):
def __init__(self):
self.graphics = []
def add(self, graphic):
self.graphics.append(graphic)
def remove(self, graphic):
self.graphics.remove(graphic)
def draw(self):
for graphic in self.graphics:
graphic.draw()
# Клиентский код
circle1 = Circle()
circle2 = Circle()
composite = CompositeGraphic()
composite.add(circle1)
composite.add(circle2)
# Рисуем все элементы
composite.draw()
Легко обрабатывать как простые, так и составные объекты.
Можно легко добавлять новые типы компонентов.
Могут возникнуть сложности при управлении более сложными структурами.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10❤1
Паттерн Фасад (Facade) — это структурный паттерн проектирования, который предоставляет упрощённый интерфейс к сложной системе классов, библиотеке или фреймворку. Основная цель паттерна — уменьшить сложность взаимодействия с системой, скрывая её внутренние детали и предоставляя более простой интерфейс для клиента.
Фасад помогает уменьшить сложность больших систем, делая их более понятными и удобными для использования. Он позволяет отделить клиентов системы от её сложных внутренних деталей, что облегчает поддержку и расширение системы.
Фасад создаётся как класс, который инкапсулирует взаимодействие с одной или несколькими подсистемами. Клиенты обращаются к этому фасаду, чтобы выполнять нужные действия, не вдаваясь в детали реализации этих действий.
# Подсистема 1
class CPU:
def freeze(self):
print("CPU freezing")
def jump(self, position):
print(f"CPU jumping to {position}")
def execute(self):
print("CPU executing")
# Подсистема 2
class Memory:
def load(self, position, data):
print(f"Memory loading {data} at {position}")
# Подсистема 3
class HardDrive:
def read(self, lba, size):
return f"Reading {size} bytes from LBA {lba}"
# Фасад
class ComputerFacade:
def __init__(self):
self.cpu = CPU()
self.memory = Memory()
self.hard_drive = HardDrive()
def start(self):
self.cpu.freeze()
self.memory.load("0x00", self.hard_drive.read("100", "1024"))
self.cpu.jump("0x00")
self.cpu.execute()
# Клиентский код
computer = ComputerFacade()
computer.start()
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥20👍9
Это поведенческий паттерн проектирования, который позволяет сохранять и восстанавливать предыдущее состояние объекта без нарушения инкапсуляции. Этот паттерн особенно полезен для реализации операций отмены и повтора, так как он позволяет хранить состояния объектов и возвращать их к этим состояниям по необходимости.
Позволяет сохранять текущее состояние объекта и восстанавливать его позже.
Обеспечивает сохранение состояния объекта без нарушения его инкапсуляции. Внутренние детали объекта остаются скрытыми от других объектов.
Поддерживает функциональность отмены и повтора операций, так как позволяет возвращать объект к предыдущим состояниям.
Пример реализации
class Memento:
def __init__(self, state: str):
self._state = state
def get_state(self) -> str:
return self._state
class TextEditor:
def __init__(self):
self._state = ""
self._history = []
def type(self, text: str):
self._save_state()
self._state += text
def _save_state(self):
self._history.append(Memento(self._state))
def undo(self):
if not self._history:
return
memento = self._history.pop()
self._state = memento.get_state()
def get_content(self) -> str:
return self._state
# Клиентский код для использования паттерна Хранитель
def main():
editor = TextEditor()
editor.type("Hello, ")
editor.type("world!")
print(editor.get_content()) # Hello, world!
editor.undo()
print(editor.get_content()) # Hello,
editor.undo()
print(editor.get_content()) #
if __name__ == "__main__":
main()
Сохраняет состояние объекта. Он предоставляет методы для получения сохраненного состояния, но не предоставляет методов для изменения состояния, что обеспечивает неизменность.
Создает и использует объекты
Memento
для сохранения и восстановления своего состояния. Методы type
и undo
позволяют редактировать текст и отменять изменения.Сохраняет текущее состояние редактора в истории перед каждым изменением.
Восстанавливает предыдущее состояние редактора из истории.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3❤1
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍26🔥8💊3
Паттерн Наблюдатель (Observer) — это поведенческий паттерн проектирования, который определяет зависимость "один ко многим" между объектами, так что при изменении состояния одного объекта все зависящие от него объекты уведомляются и обновляются автоматически. Этот паттерн используется для реализации механизма подписки, когда объекты могут подписываться на события другого объекта и получать уведомления о любых изменениях.
Позволяет отделить объект, который изменяет свое состояние, от объектов, которые реагируют на эти изменения.
Обеспечивает автоматическое уведомление и обновление зависимых объектов при изменении состояния наблюдаемого объекта.
Легко добавлять или удалять наблюдателей без изменения кода наблюдаемого объекта.
Пример реализации
from abc import ABC, abstractmethod
class Observer(ABC):
@abstractmethod
def update(self, message: str):
pass
class ConcreteObserver(Observer):
def __init__(self, name: str):
self._name = name
def update(self, message: str):
print(f"{self._name} received message: {message}")
class Subject:
def __init__(self):
self._observers = []
def add_observer(self, observer: Observer):
self._observers.append(observer)
def remove_observer(self, observer: Observer):
self._observers.remove(observer)
def notify_observers(self, message: str):
for observer in self._observers:
observer.update(message)
# Клиентский код для использования паттерна Наблюдатель
def main():
subject = Subject()
observer1 = ConcreteObserver("Observer 1")
observer2 = ConcreteObserver("Observer 2")
subject.add_observer(observer1)
subject.add_observer(observer2)
subject.notify_observers("Event 1") # Observer 1 received message: Event 1
# Observer 2 received message: Event 1
subject.remove_observer(observer1)
subject.notify_observers("Event 2") # Observer 2 received message: Event 2
if __name__ == "__main__":
main()
Объявляет метод
update
, который должны реализовать все конкретные наблюдатели.Реализует интерфейс
Observer
и определяет, как наблюдатель должен реагировать на обновления.Содержит список наблюдателей и методы для добавления, удаления и уведомления наблюдателей.
Вызывается при изменении состояния субъекта и уведомляет всех зарегистрированных наблюдателей.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍22🔥7💊2❤1
Это поведенческий паттерн проектирования, который позволяет объекту изменять свое поведение в зависимости от его состояния. Это делается путем инкапсуляции состояний в отдельные классы и делегирования задач состояниям, таким образом объект изменяет свой класс поведения при изменении состояния.
Логика, связанная с конкретными состояниями, инкапсулируется в отдельных классах, что способствует лучшему разделению обязанностей и поддержке кода.
Легко добавлять новые состояния и изменять существующие без внесения изменений в основной код объекта.
from abc import ABC, abstractmethod
# Интерфейс состояния
class State(ABC):
@abstractmethod
def insert_coin(self):
pass
@abstractmethod
def eject_coin(self):
pass
@abstractmethod
def dispense(self):
pass
# Конкретные состояния
class NoCoinState(State):
def __init__(self, machine):
self.machine = machine
def insert_coin(self):
print("Coin inserted.")
self.machine.set_state(self.machine.has_coin_state)
def eject_coin(self):
print("No coin to eject.")
def dispense(self):
print("Insert coin first.")
class HasCoinState(State):
def __init__(self, machine):
self.machine = machine
def insert_coin(self):
print("Coin already inserted.")
def eject_coin(self):
print("Coin ejected.")
self.machine.set_state(self.machine.no_coin_state)
def dispense(self):
print("Dispensing product.")
self.machine.set_state(self.machine.no_coin_state)
# Контекст
class VendingMachine:
def __init__(self):
self.no_coin_state = NoCoinState(self)
self.has_coin_state = HasCoinState(self)
self.state = self.no_coin_state
def set_state(self, state: State):
self.state = state
def insert_coin(self):
self.state.insert_coin()
def eject_coin(self):
self.state.eject_coin()
def dispense(self):
self.state.dispense()
# Клиентский код
def main():
machine = VendingMachine()
machine.insert_coin() # Coin inserted.
machine.dispense() # Dispensing product.
machine.eject_coin() # No coin to eject.
machine.insert_coin() # Coin inserted.
machine.eject_coin() # Coin ejected.
machine.dispense() # Insert coin first.
if __name__ == "__main__":
main()
Определяет методы, которые должны реализовать все конкретные состояния.
Реализуют интерфейс
State
и определяют поведение для каждого состояния.Содержит ссылки на все возможные состояния и метод для изменения текущего состояния. Делегирует вызовы методов текущему состоянию.
Вызываются клиентом и делегируются текущему состоянию.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍22🔥10
Это технология, позволяющая программам выполнять процедуры или функции на удаленных системах так же, как если бы они выполнялись локально. RPC абстрагирует сетевое взаимодействие, делая удаленные вызовы процедур похожими на локальные вызовы, что упрощает распределенное программирование.
Позволяет разработчикам вызывать удаленные процедуры так, как будто они находятся на локальной машине, что упрощает программирование распределенных систем.
Скрывает сложность сетевого взаимодействия, позволяя сосредоточиться на логике приложения.
Обеспечивает взаимодействие между приложениями, работающими на разных платформах и написанных на разных языках программирования.
Инициирует вызов удаленной процедуры, отправляя запрос на сервер.
Принимает запрос, выполняет запрашиваемую процедуру и возвращает результат клиенту.
Сервер
from xmlrpc.server import SimpleXMLRPCServer
def add(x, y):
return x + y
def main():
server = SimpleXMLRPCServer(("localhost", 8000))
print("Listening on port 8000...")
server.register_function(add, "add")
server.serve_forever()
if __name__ == "__main__":
main()
Клиентские и серверные заглушки генерируются для сериализации и десериализации данных, что позволяет передавать данные по сети.
Клиент
import xmlrpc.client
def main():
with xmlrpc.client.ServerProxy("https://localhost:8000/") as proxy:
result = proxy.add(5, 3)
print(f"5 + 3 = {result}")
if __name__ == "__main__":
main()
Создает XML-RPC сервер и регистрирует функцию
add
, которая принимает два числа и возвращает их сумму. Сервер ожидает запросы на порту 8000.Подключается к серверу через
ServerProxy
и вызывает удаленную функцию add
с аргументами 5 и 3. Результат вызова выводится на экран.Обеспечивает простой интерфейс для вызова удаленных процедур.
Меньше задержек по сравнению с передачей сообщений благодаря синхронным вызовам.
Поддерживает взаимодействие между системами на разных платформах и языках программирования.
Работа системы зависит от сетевого соединения, что может приводить к задержкам и ошибкам.
Ошибки и проблемы могут быть сложными для диагностики из-за распределенной природы системы.
Необходимо обеспечить безопасность данных, передаваемых по сети, особенно при использовании в открытых сетях.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍11🔥4💊1
Это механизм кэширования, который использует стратегию "наименее недавно использованный" для управления хранимыми данными. LRU-кэш хранит фиксированное количество наиболее часто используемых элементов, удаляя наименее недавно использованные элементы, когда необходимо освободить место для новых.
Повышает производительность системы за счет хранения часто запрашиваемых данных в памяти.
Поддерживает ограниченный размер кэша, автоматически удаляя наименее недавно использованные элементы.
Снижает время доступа к данным, которые часто используются, избегая повторных вычислений или запросов к медленным хранилищам.
Python предоставляет удобную реализацию LRU-кэша через декоратор
lru_cache
в модуле functools
. Этот декоратор можно использовать для кэширования результатов вызова функции.from functools import lru_cache
@lru_cache(maxsize=4)
def expensive_computation(n):
print(f"Computing {n}...")
return n * n
def main():
print(expensive_computation(1)) # Computing 1... -> 1
print(expensive_computation(2)) # Computing 2... -> 4
print(expensive_computation(3)) # Computing 3... -> 9
print(expensive_computation(4)) # Computing 4... -> 16
print(expensive_computation(1)) # Cached -> 1
print(expensive_computation(2)) # Cached -> 4
print(expensive_computation(5)) # Computing 5... -> 25 (1 removed from cache)
print(expensive_computation(3)) # Cached -> 9
print(expensive_computation(1)) # Computing 1... -> 1 (2 removed from cache)
if __name__ == "__main__":
main()
Декорирует функцию
expensive_computation
, добавляя механизм кэширования.Определяет максимальный размер кэша. В данном примере, кэш может хранить до 4 элементов.
При вызове функции сначала проверяется, есть ли результат в кэше. Если есть, возвращается кэшированный результат. Если нет, функция вычисляет результат, и он сохраняется в кэш. Когда кэш переполняется, наименее недавно использованный элемент удаляется.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍13
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍29🔥5💊1
Это поведенческий паттерн проектирования, который определяет скелет алгоритма в методе, оставляя реализацию некоторых шагов подклассам. Этот паттерн позволяет подклассам переопределять определенные шаги алгоритма, не изменяя его структуру.
Позволяет повторно использовать код, инкапсулируя общие части алгоритма в базовом классе и оставляя вариативные части для реализации в подклассах.
Легко изменять и расширять части алгоритма, переопределяя методы в подклассах.
Базовый класс контролирует структуру алгоритма, предотвращая нежелательные изменения его последовательности.
Пример реализации паттерна Шаблонный метод для процесса приготовления кофе и чая. Общие шаги включают кипячение воды, заваривание напитка и добавление добавок, но конкретные шаги зависят от типа напитка.
from abc import ABC, abstractmethod
class CaffeineBeverage(ABC):
def prepare_recipe(self):
self.boil_water()
self.brew()
self.pour_in_cup()
self.add_condiments()
def boil_water(self):
print("Boiling water")
def pour_in_cup(self):
print("Pouring into cup")
@abstractmethod
def brew(self):
pass
@abstractmethod
def add_condiments(self):
pass
class Tea(CaffeineBeverage):
def brew(self):
print("Steeping the tea")
def add_condiments(self):
print("Adding lemon")
class Coffee(CaffeineBeverage):
def brew(self):
print("Dripping coffee through filter")
def add_condiments(self):
print("Adding sugar and milk")
# Клиентский код для использования паттерна Шаблонный метод
def main():
tea = Tea()
coffee = Coffee()
print("Making tea:")
tea.prepare_recipe()
print("\nMaking coffee:")
coffee.prepare_recipe()
if __name__ == "__main__":
main()
Определяет шаблонный метод
prepare_recipe
, который описывает последовательность шагов алгоритма.Реализованы в абстрактном классе, так как они одинаковы для всех напитков.
Объявлены в абстрактном классе и должны быть реализованы в подклассах.
Реализуют методы
brew
и add_condiments
, определяя конкретные шаги для приготовления чая и кофе.Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8❤1