Расскажи о шаблонном проектировании, которое ты использовал в своей разработке.
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): Определяет семейство алгоритмов, инкапсулирует каждый из них и делает их взаимозаменяемыми. Позволяет алгоритму варьироваться независимо от клиентов, которые его используют. Использовал для реализации различных подходов к сортировке данных, валидации форм или обработке событий.
Использование этих шаблонов помогало создавать более структурированный, модульный, тестируемый и поддерживаемый код.