Паттерн Мост (Bridge) — это структурный паттерн проектирования, который позволяет нам отделить абстракции от реализаций и сделать их независимыми друг от друга. В результате абстракции и реализации могут разрабатываться как отдельные сущности. Паттерн Мост считается одним из лучших методов организации иерархии классов. Но давайте поподробнее разберем, что всё это значит.
Давайте представим, что у нас есть класс Cuboid (параллелепипед), который имеет три атрибута: length (длина), breadth (ширина) и height (высота). Также он имеет три метода: ProducewithAPI(), ProduceWithAPI2() и expand().
Два метода зависят от реализации, поскольку у нас есть два API, а один метод — expand() — не зависит.
Пока у нас всего три метода, все в порядке. Но в масштабируемом проекте их количество может вырасти, и тогда разработчикам станет крайне сложно с ними справляться. Посмотрите, как быстро может разрастись такая структура:
Следующий код написан без использования паттерна Мост:
""" Code without using the bridge method
We have a class with three attributes
named as length, breadth, and height and
three methods named as ProduceWithAPI1(),
ProduceWithAPI2(), and expand(). Out of these
producing methods are implementation-specific
as we have two production APIs"""
class Cuboid:
class ProducingAPI1:
"""Implementation Specific Implementation"""
def produceCuboid(self, length, breadth, height):
print(f'API1 is producing Cuboid with length = {length}, '
f' Breadth = {breadth} and Height = {height}')
class ProducingAPI2:
"""Implementation Specific Implementation"""
def produceCuboid(self, length, breadth, height):
print(f'API2 is producing Cuboid with length = {length}, '
f' Breadth = {breadth} and Height = {height}')
def __init__(self, length, breadth, height):
"""Initialize the necessary attributes"""
self._length = length
self._breadth = breadth
self._height = height
def produceWithAPI1(self):
"""Implementation specific Abstraction"""
objectAPIone = self.ProducingAPI1()
objectAPIone.produceCuboid(self._length, self._breadth, self._height)
def producewithAPI2(self):
"""Implementation specific Abstraction"""
objectAPItwo = self.ProducingAPI2()
objectAPItwo.produceCuboid(self._length, self._breadth, self._height)
def expand(self, times):
"""Implementation independent Abstraction"""
self._length = self._length * times
self._breadth = self._breadth * times
self._height = self._height * times
# Instantiate a Cubiod
cuboid1 = Cuboid(1, 2, 3)
# Draw it using APIone
cuboid1.produceWithAPI1()
# Instantiate another Cuboid
cuboid2 = Cuboid(19, 20, 21)
# Draw it using APItwo
cuboid2.producewithAPI2()
Теперь давайте посмотрим на решение вышеуказанной проблемы с использованием паттерна Мост. Данный паттерн является одним из лучших решений для такого рода проблем.
Наша основная задача — разделить код абстракции и реализации. В результате мы получим следующую структуру:
Следующий код написан с использованием паттерна Мост:
"""Code implemented with Bridge Method.
We have a Cuboid class having three attributes
named as length, breadth, and height and three
methods named as produceWithAPIOne(), produceWithAPItwo(),
and expand(). Our purpose is to separate out implementation
specific abstraction from implementation-independent
abstraction"""
class ProducingAPI1:
"""Implementation specific Abstraction"""
def produceCuboid(self, length, breadth, height):
print(f'API1 is producing Cuboid with length = {length}, '
f' Breadth = {breadth} and Height = {height}')
class ProducingAPI2:
"""Implementation specific Abstraction"""
def produceCuboid(self, length, breadth, height):
print(f'API2 is producing Cuboid with length = {length}, '
f' Breadth = {breadth} and Height = {height}')
class Cuboid:
def __init__(self, length, breadth, height, producingAPI):
"""Initialize the necessary attributes
Implementation independent Abstraction"""
self._length = length
self._breadth = breadth
self._height = height
self._producingAPI = producingAPI
def produce(self):
"""Implementation specific Abstraction"""
self._producingAPI.produceCuboid(self._length, self._breadth, self._height)
def expand(self, times):
"""Implementation independent Abstraction"""
self._length = self._length * times
self._breadth = self._breadth * times
self._height = self._height * times
"""Instantiate a cuboid and pass to it an
object of ProducingAPIone"""
cuboid1 = Cuboid(1, 2, 3, ProducingAPI1())
cuboid1.produce()
cuboid2 = Cuboid(19, 19, 19, ProducingAPI2())
cuboid2.produce()
Вот так будет выглядеть UML-диаграмма паттерна Мост:
Итак, мы познакомились с паттерном проектирования Мост (Bridge). Теперь вы знаете, какую проблему он решает и как применяется. Кроме того, мы разобрали преимущества и недостатки данного паттерна.
Надеемся, данная статья была вам полезна! Успехов в написании кода!
Перевод статьи «Bridge Method – Python Design Patterns».
Если вы ищете работу на Python, на Talanto.work сейчас есть варианты для junior, middle, senior…
Рынок Python-вакансий большой, но удобным его назвать сложно. Формально вакансий много, однако в реальном поиске…
Срезы в Python — это больше, чем a[2:7]. В статье — быстрый разбор полезных приёмов:…
В этой статье мы рассмотрим возведение в степень в Python с помощью различных методов, от…
Дубликаты в списке Python — частая проблема. В статье показано, как быстро убрать повторы, в…
Услуга виртуального хостинга на SpaceWeb позволяет арендовать часть сервера (shared-сервера) и разместить на нём свой…