Фабричный метод в React: эффективное создание компонентов. Часть 1

от автора

Привет всем! Я Мыльников Кирилл, frontend-разработчик в компании Usetech. Сегодня хочу поделиться примером реализации фабричного метода во фронтенде и объяснить, когда и где его следует применять. Освежим память о паттернах и роли, которую они играют в проектах.

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

Давайте по классике начнем с определений, вспомним, что такое паттерны и фабричный метод.

Что такое паттерн?

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

Что такое «Фабричный метод»?

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

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

Давайте теперь все это адаптируем под наш проект на React.

Фабричный метод в React

В React фабричный метод служит для динамического создания компонентов или функций с различными свойствами или поведениями. Представьте фабрику, где товары создаются по заказу с уникальными параметрами: размером, цветом и материалом. Здесь процесс создания товаров автоматизирован, что позволяет изготавливать предметы без необходимости их ручной настройки. Также и в React мы можем создать фабричную функцию для компонентов.

Так давайте же перейдем от теории к практике. Все примеры буду показывать в песочнице, сначала буду описывать проблему, которая может возникнуть в проекте, а потом сразу покажу решение через фабричный метод.

Реализация фабричного метода в React

Будем использовать для тестовых данных вот этот сервис DummyJSON.

Вот ссылка на codesandbox с примером. В первом случае список отображается там, где могут возникнуть проблемы при внедрении или изменении логики в дальнейшем, а во втором – применен паттерн «Фабричный метод». Мы получаем список продуктов и выводим их, но при различных категориях нам приходится настраивать каждую карточку индивидуально.

Компонент становится сложным и трудночитаемым из-за условий, и изменения могут нарушить логику других категорий, но это можно исправить с помощью паттерна «Фабричный метод».

Пример

const Product = ({ product }: IProductProps) => {   return (     <li>       <div className={styles.product}>         <img src={product.thumbnail} alt="thumbnail" />       </div>       <div className={styles.productInfo}>         {product.category !== "beauty" && (           <p className={styles.productTitle}>{product.title}</p>         )}         <p className={styles.productPrice}>${product.price}</p>       </div>       {product.category === "groceries" && (         <p className={styles.description}>{product.description}</p>       )}       {product.category === "fragrances" && (         <p className={styles.policy}>           <span className={styles.text}> Условия возврата: </span>           {product.returnPolicy}         </p>       )}     </li>   ); };  export default Product;

Вот наша вторая реализация, где мы применяем паттерн «Фабричный метод». Это позволяет нам легко вносить изменения и настраивать каждую карточку в зависимости от категории. Теперь мы можем без проблем изменять логику для каждого типа продукта, и никакие изменения не затронут другие категории. Не забываем, что можно перейти по ссылке и посмотреть пример полностью – codesandbox.

Пример

import { IProducts } from "../../../../typings"; import BeatuProduct from "./BeautyProduct"; import GroceriesProduct from "./GroceriesProduct"; import FragrancesProduct from "./FragrancesProduct";  interface IProductFactoryProps {   product: IProducts; }  const ProductFactory = ({ product }: IProductFactoryProps) => {   switch (product.category) {     case "beauty":       return <BeautyProduct product={product} />;     case "groceries":       return <GroceriesProduct product={product} />;     case "fragrances":       return <FragrancesProduct product={product} />;     default:       return null;   } };  export default ProductFactory;

Еще один наглядный пример использования фабричного метода это UI – компоненты, допустим у нас в проекте есть кнопка, которая может выглядеть по-разному в различных частях интерфейса – с разными цветами и темами. В рассмотренном примере ниже мы видим, что в зависимости от типа кнопки мы отображаем конкретный компонент кнопки со своими стилями и свойствами. Благодаря использованию паттерна «Фабричный метод», нам легко и просто настраивать кнопку под нужды проекта и в любой момент заменять ее другой кнопкой с новым типом или добавить новый тип и настроить через новый компонент, реализация тут – codesanbox.

Пример

import DangerButton from "./DangerButton"; import PrimaryButton from "./PrimaryButton";  export interface IButtonProps {   type: "primary" | "danger";   title: string;   onClick?: () => void; }  const Button = ({ type, title, onClick }: IButtonProps) => {   switch (type) {     case "primary":       return <PrimaryButton title={title} onClick={onClick} />;     case "danger":       return <DangerButton title={title} onClick={onClick} />;     default:       return null;   } };  export default Button;

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

Материалы

Паттерны – Каталог паттернов проектирования (refactoringguru.cn)

Codesanbox – ProductFactory.tsx – sandbox – CodeSandbox


ссылка на оригинал статьи https://habr.com/ru/articles/825074/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *