Долгое время думала, что использовать паттерны на фронте незачем и это больше тема для собесов
Но недавно все-таки удалось использовать паттерн фабрику для фронта и моему счастью не было предела, когда после 30-минутного рефакторинга разъехавшейся вёрстки через Claude, я попросила: "брат, слушай это ж паттерн фабрика, сделай BaseModal тонким, который просто решает, какой компонент отрисовать"
Технически, классический GoF Factory Method подразумевает наследование, а здесь у меня скорее Simple Factory — функция, выбирающая что создать. Но в обиходе все называют это "фабрикой", и я не буду усложнять.
Классический паттерн фабрика на Java:
// Интерфейс
interface Modal {
void open();
void close();
}
// Конкретные реализации
class Dialog implements Modal { ... }
class BottomSheet implements Modal { ... }
class FullscreenSheet implements Modal { ... }
// Фабрика — решает какой класс создать
class ModalFactory {
static Modal create(String type, boolean isMobile) {
if (!isMobile) return new Dialog();
return switch (type) {
case "bottom-sheet" -> new BottomSheet();
case "fullscreen" -> new FullscreenSheet();
default -> new Dialog();
};
}
}
// Использование
Modal modal = ModalFactory.create("bottom-sheet", isMobile);
modal.open();
Как это работает во Vue?
На фронте есть <component :is="..."/> - динамический компонент, который рендерит то, что ему передадут. Это и есть наш аналог ModalFactory.create(...).
<!-- BaseModal.vue — фабрика -->
<template>
<component
:is="modalComponent"
v-bind="$props"
@close="emit('close')"
>
<slot />
</component>
</template>
<script setup>
// Фабричный метод — выбирает компонент
const modalComponent = computed(() => {
// Desktop → всегда Dialog (центрированный)
if (!isMobile.value) return BaseDialog
// Mobile → зависит от mobileStyle
switch (props.mobileStyle) {
case 'fullscreen':
return BaseFullscreenSheet
case 'bottom-sheet':
return BaseBottomSheet
default:
return BaseDialog
}
})
</script>
Получился BaseModal, который сам почти ничего не делает.
Он не знает, как устроен dialog. Не знает, как анимируется bottom sheet. Не знает, как выглядит fullscreen-модалка.