Аскаров Алмаз Димович
Фабричный метод — это пораждающий шаблон проектирования, используемый для создания конкретных реализаций общего интерфейса.
Он позволяет разделить процесс создания объекта от кода, который зависит от интерфейса объекта.
Например, приложению требуется объект с определенным интерфейсом. Это может объект у которого конкретная реализация интерфейса зависит от некоторого параметра.
Вместо того, чтобы использовать сложную условную структуру if/elif/else для выбора конкретной реализации, приложение делегирует это решение отдельному компоненту, который создает объект. При таком подходе код приложения упрощается, что делает его более удобным для повторного использования и обслуживания.
В качестве примера мы будем использовать некоторое выдуманное приложение, которому необходимо преобразовать объект Song в его текстовое представление в нужном формате. Преобразование объекта в другое представление часто называется сериализацией. Возможно вы часто видели эту задачу реализованную в одной функции или методе, которые содержат всю логику и реализацию, как в следующем примере коде:
Представьте, что у вас есть собственный стартап, который предоставляет райдшеринг в разных частях страны. Первоначальная версия приложения обеспечивает только совместное использование двухколесных транспортных средств, но со временем ваше приложение становится популярным, и теперь вы также хотите добавить совместное использование трех- и четырехколесных транспортных средств. Это отличная новость! Но как быть с разработчиками программного обеспечения вашего стартапа. Они должны изменить весь код, потому что теперь большая часть кода связана с классом Two-Wheeler, и разработчики должны вносить изменения во всю кодовую базу. После того, как со всеми этими изменениями покончено, разработчики заканчивают либо грязным кодом, либо письмом об отставке. Давайте разберемся с концепцией еще на одном примере, который связан с переводами и локализацией разных языков. Предположим, мы создали приложение, основной целью которого является перевод с одного языка на другой, и в настоящее время наше приложение работает только с 10 языками. Сейчас наше приложение стало широко популярным среди людей, но спрос внезапно вырос и включает в себя еще 5 языков. Это отличная новость! Только для владельца, а не для разработчиков. Им приходится менять весь код, потому что теперь большая часть кода связана только с существующими языками, и поэтому разработчикам приходится вносить изменения во всю кодовую базу, что действительно сложно сделать.Давайте посмотрим на код для проблемы, с которой мы можем столкнуться без использования фабричного метода.
""" it simply returns the french version """
def __init__(self):
self.translations = {"car": "voiture", "bike": "bicyclette",
"cycle":"cyclette"}
def localize(self, msg):
"""change the message using translations"""
return self.translations.get(msg, msg)
class SpanishLocalizer:
"""it simply returns the spanish version"""
def __init__(self):
self.translations = {"car": "coche", "bike": "bicicleta",
"cycle":"ciclo"}
def localize(self, msg):
"""change the message using translations"""
return self.translations.get(msg, msg)
class EnglishLocalizer:
"""Simply return the same message"""
def localize(self, msg):
return msg
if __name__ == "__main__":
# main method to call others
f = FrenchLocalizer()
e = EnglishLocalizer()
s = SpanishLocalizer()
# list of strings
message = ["car", "bike", "cycle"]
for msg in message:
print(f.localize(msg))
print(e.localize(msg))
print(s.localize(msg))
Его решение состоит в том, чтобы заменить простые вызовы построения объекта вызовами специального фабричного метода. На самом деле, не будет никакой разницы в создании объектов, но они вызываются в рамках фабричного метода. Например, наши классы Two_Wheeler, Three_Wheeler и Four_wheeler должны реализовывать интерфейс совместного использования, который объявит метод, называемый поездкой. Каждый класс будет реализовывать этот метод уникально.
""" it simply returns the french version """
def __init__(self):
self.translations = {"car": "voiture", "bike": "bicyclette",
"cycle":"cyclette"}
def localize(self, msg):
"""change the message using translations"""
return self.translations.get(msg, msg)
class SpanishLocalizer:
"""it simply returns the spanish version"""
def __init__(self):
self.translations = {"car": "coche", "bike": "bicicleta",
"cycle":"ciclo"}
def localize(self, msg):
"""change the message using translations"""
return self.translations.get(msg, msg)
class EnglishLocalizer:
"""Simply return the same message"""
def localize(self, msg):
return msg
def Factory(language ="English"):
"""Factory Method"""
localizers = {
"French": FrenchLocalizer,
"English": EnglishLocalizer,
"Spanish": SpanishLocalizer,
}
return localizers[language]()
if __name__ == "__main__":
f = Factory("French")
e = Factory("English")
s = Factory("Spanish")
message = ["car", "bike", "cycle"]
for msg in message:
print(f.localize(msg))
print(e.localize(msg))
print(s.localize(msg))
Давайте посмотрим на диаграмму классов на примере райдшеринга.
*Мы можем легко добавлять новые типы продуктов, не нарушая существующий клиентский код. *Как правило, избегается тесная связь между продуктами и классами и объектами создателей.
- Чтобы создать конкретный конкретный объект продукта, клиенту, возможно, придется создать подкласс класса создателя.
- В итоге вы получаете огромное количество мелких файлов, т.е. загромождаете файлы.
- В графической системе, в зависимости от ввода пользователя, он может рисовать различные формы, такие как прямоугольники, квадраты, круги и т. Д. Но для простоты как разработчиков, так и клиента мы можем использовать фабричный метод для создания экземпляра в зависимости от ввода пользователя. Тогда нам не нужно менять клиентский код для добавления новой фигуры. На сайте бронирования отелей мы можем забронировать слот на 1 комнату, 2 комнаты, 3 комнаты и т. Д. Здесь пользователь может ввести количество номеров, которые он хочет забронировать. Используя фабричный метод, мы можем создать фабричный класс Any Rooms, который поможет нам создать экземпляр в зависимости от ввода пользователя. Опять же, нам не нужно менять код клиента для добавления нового объекта.