Назад к вопросам
Middle+
77
questionbank

Расскажи о шаблонном проектировании, которое ты использовал в своей разработке.

Sobes Copilot

Получайте ответы в реальном времени

Ответ от нейросети

sobes.tech AI

Использовал следующие шаблоны проектирования:

  • MVC (Model-View-Controller): Разделение логики приложения. Модель управляет данными, Представление отвечает за отображение, а Контроллер обрабатывает взаимодействие пользователя и обновляет Модель или Представление. Применял в Angular, где компоненты частично реализуют эту идеологию.

  • MVVM (Model-View-ViewModel): Похож на MVC, но вводит ViewModel как посредника между Представлением и Моделью. ViewModel содержит бизнес-логику для отображения данных и обработки действий пользователя. Активно использовал при работе с React и Vuex (Vue), где состояние приложения управляется централизованно.

    // Пример реактивности в React с использованием useState
    import React, { useState } from 'react';
    
    function Counter() {
      const [count, setCount] = useState(0); // useState - часть механизма MVVM
    
      const increment = () => {
        setCount(count + 1); // Обновление состояния через сеттер
      };
    
      return (
        <div>
          <p>Count: {count}</p> {/* Отображение состояния */}
          <button onClick={increment}>Increment</button> {/* Действие, влияющее на состояние */}
        </div>
      );
    }
    
  • Компонентный паттерн: Разбиение пользовательского интерфейса на независимые, переиспользуемые компоненты. Каждый компонент инкапсулирует свою логику, разметку и стили. Лежит в основе современных фреймворков, таких как React, Vue и Angular.

    // Пример простого компонента React
    function Button(props) {
      return (
        <button className="my-button" onClick={props.onClick}>
          {props.label}
        </button>
      );
    }
    
  • Адаптер (Adapter): Преобразует интерфейс одного класса в другой, который ожидают клиенты. Позволяет работать классам с несовместимыми интерфейсами вместе. Применял для интеграции сторонних библиотек или API с разными сигнатурами методов.

    // Пример адаптера для работы с разными API-клиентами
    class OldApi {
      getDataOld(id) {
        console.log(`Getting data from Old API for id ${id}`);
        return { id: id, name: `Item ${id}` };
      }
    }
    
    class NewApi {
      fetchDataNew(itemId) {
        console.log(`Fetching data from New API for item id ${itemId}`);
        return { itemId: itemId, label: `Product ${itemId}` };
      }
    }
    
    class ApiAdapter {
      constructor(apiClient) {
        this.apiClient = apiClient;
      }
    
      getData(id) {
        if (this.apiClient instanceof OldApi) {
          return this.apiClient.getDataOld(id);
        } else if (this.apiClient instanceof NewApi) {
          // Преобразование данных из нового формата
          const newData = this.apiClient.fetchDataNew(id);
          return { id: newData.itemId, name: newData.label };
        }
        throw new Error("Unsupported API client");
      }
    }
    
    const oldApiAdapter = new ApiAdapter(new OldApi());
    console.log(oldApiAdapter.getData(1));
    
    const newApiAdapter = new ApiAdapter(new NewApi());
    console.log(newApiAdapter.getData(2));
    
  • Итератор (Iterator): Предоставляет способ последовательного доступа к элементам составного объекта, не раскрывая его внутреннего представления. Используется в циклах (for...of) и методах массивов (forEach, map, filter).

    // Пример использования итератора в JavaScript
    const numbers = [1, 2, 3, 4, 5];
    
    // Явное получение итератора
    const iterator = numbers[Symbol.iterator]();
    
    console.log(iterator.next()); // { value: 1, done: false }
    console.log(iterator.next()); // { value: 2, done: false }
    // ...
    console.log(iterator.next()); // { value: undefined, done: true }
    
    // Использование итератора в for...of
    for (const number of numbers) {
      console.log(number);
    }
    
  • Декоратор (Decorator): Динамически добавляет новые обязанности объекту, позволяя расширять функциональность объекта без изменения его структуры. Использовал в виде HOC (Higher-Order Components) в React или декораторов в Angular/TypeScript.

    // Пример Higher-Order Component (HOC) в React
    function withLogging(WrappedComponent) {
      return function WithLogging(props) {
        console.log(`Component ${WrappedComponent.name} rendered with props:`, props);
        return <WrappedComponent {...props} />;
      };
    }
    
    // Применение HOC
    const EnhancedButton = withLogging(Button);
    
    // Использование улучшенного компонента
    // <EnhancedButton label="Click me" onClick={() => console.log('Clicked!')} />
    
  • Одиночка (Singleton): Гарантирует, что у класса есть только один экземпляр, и предоставляет глобальную точку доступа к нему. Применял для управления глобальным состоянием приложения или для создания единого экземпляра сервиса (например, сервиса логирования, конфигурации).

    // Пример шаблона Одиночка
    class ConfigManager {
      constructor() {
        if (ConfigManager.instance) {
          return ConfigManager.instance;
        }
        this.settings = {}; // Инициализация настроек
        ConfigManager.instance = this;
      }
    
      setSetting(key, value) {
        this.settings[key] = value;
      }
    
      getSetting(key) {
        return this.settings[key];
      }
    }
    
    const config1 = new ConfigManager();
    const config2 = new ConfigManager();
    
    console.log(config1 === config2); // true (один и тот же экземпляр)
    
    config1.setSetting('apiUrl', 'https://api.example.com');
    console.log(config2.getSetting('apiUrl')); // https://api.example.com
    
  • Фабричный метод (Factory Method): Определяет интерфейс для создания объекта, но позволяет подклассам решать, какой объект создавать. Применял для создания различных типов элементов пользовательского интерфейса или объектов на основе конфигурации.

  • Стратегия (Strategy): Определяет семейство алгоритмов, инкапсулирует каждый из них и делает их взаимозаменяемыми. Позволяет алгоритму варьироваться независимо от клиентов, которые его используют. Использовал для реализации различных подходов к сортировке данных, валидации форм или обработке событий.

Использование этих шаблонов помогало создавать более структурированный, модульный, тестируемый и поддерживаемый код.