← Назад к вопросам

Какие знаешь паттерны?

1.6 Junior🔥 171 комментариев
#Архитектура и паттерны

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Какие знаешь паттерны?

Паттерны (patterns) — это проверенные решения для типичных проблем в программировании. Я знаю множество паттернов разных категорий. Расскажу о самых полезных для фронтенда.

Архитектурные паттерны

1. MVC (Model-View-Controller)

Разделение на три слоя:

  • Model — бизнес-логика и данные
  • View — интерфейс
  • Controller — связь между ними
// Model — данные и логика
class UserModel {
  constructor() {
    this.users = []
  }
  
  addUser(name) {
    this.users.push({ id: Date.now(), name })
  }
}

// View — интерфейс
class UserView {
  render(users) {
    return `
      <ul>
        ${users.map(u => `<li>${u.name}</li>`).join('')}
      </ul>
    `
  }
}

// Controller — связь
class UserController {
  constructor(model, view) {
    this.model = model
    this.view = view
  }
  
  addUser(name) {
    this.model.addUser(name)
    this.render()
  }
  
  render() {
    const html = this.view.render(this.model.users)
    document.body.innerHTML = html
  }
}

2. MVVM (Model-View-ViewModel)

Используется в Vue и Angular. Двусторонняя привязка данных.

// Vue использует MVVM
const vm = new Vue({
  el: '#app',
  data() {  // ViewModel
    return { message: 'Hello' }
  },
  template: '<h1>{{ message }}</h1>'  // View
})

// Изменение View -> ViewModel -> Model
// Изменение Model -> ViewModel -> View (автоматически)

3. Redux / Flux

Паттерн управления состоянием (state management).

// Action — событие
const ADD_USER = 'ADD_USER'
const addUser = (name) => ({ type: ADD_USER, payload: name })

// Reducer — обновляет состояние
const userReducer = (state = [], action) => {
  if (action.type === ADD_USER) {
    return [...state, { id: Date.now(), name: action.payload }]
  }
  return state
}

// Store — хранилище
const store = createStore(userReducer)

// Dispatch — отправляем action
store.dispatch(addUser('John'))

Поведенческие паттерны

1. Observer (Наблюдатель)

Объект уведомляет подписчиков об изменениях.

class EventEmitter {
  constructor() {
    this.events = {}
  }
  
  on(event, callback) {
    if (!this.events[event]) {
      this.events[event] = []
    }
    this.events[event].push(callback)
  }
  
  emit(event, data) {
    if (this.events[event]) {
      this.events[event].forEach(cb => cb(data))
    }
  }
}

const emitter = new EventEmitter()
emitter.on('user:login', (user) => {
  console.log('User logged in:', user)
})
emitter.emit('user:login', { name: 'John' })

2. Strategy (Стратегия)

Выбор алгоритма во время выполнения.

const strategies = {
  linear: (value) => value,
  quad: (value) => value * value,
  sqrt: (value) => Math.sqrt(value)
}

class Calculator {
  constructor(strategy) {
    this.strategy = strategy
  }
  
  calculate(value) {
    return this.strategy(value)
  }
}

const calc = new Calculator(strategies.quad)
console.log(calc.calculate(5))  // 25

3. Chain of Responsibility (Цепочка ответственности)

Передача запроса по цепочке обработчиков.

class Logger {
  constructor(nextHandler) {
    this.next = nextHandler
  }
  
  handle(request) {
    if (request.type === 'log') {
      console.log('Logging:', request.data)
    }
    
    if (this.next) {
      this.next.handle(request)
    }
  }
}

class EmailHandler {
  constructor(nextHandler) {
    this.next = nextHandler
  }
  
  handle(request) {
    if (request.type === 'email') {
      console.log('Sending email:', request.data)
    }
    
    if (this.next) {
      this.next.handle(request)
    }
  }
}

const logger = new Logger(new EmailHandler())
logger.handle({ type: 'log', data: 'Something happened' })
logger.handle({ type: 'email', data: 'Alert' })

Структурные паттерны

1. Decorator (Декоратор)

Добавляет функциональность к объекту динамически.

function withLogging(fn) {
  return function(...args) {
    console.log('Calling:', fn.name, args)
    const result = fn(...args)
    console.log('Result:', result)
    return result
  }
}

const add = (a, b) => a + b
const addWithLogging = withLogging(add)
addWithLogging(2, 3)  // Логирует и вызывает

TypeScript декораторы:

function Log(target, propertyKey, descriptor) {
  const original = descriptor.value
  
  descriptor.value = function(...args) {
    console.log('Calling:', propertyKey)
    return original.apply(this, args)
  }
  
  return descriptor
}

class Calculator {
  @Log
  add(a: number, b: number) {
    return a + b
  }
}

2. Adapter (Адаптер)

Меняет интерфейс несовместимого объекта.

// Старая библиотека
class OldAPI {
  fetchData() {
    return { userData: { name: 'John' } }
  }
}

// Адаптер
class APIAdapter {
  constructor(oldAPI) {
    this.api = oldAPI
  }
  
  getUser() {
    const data = this.api.fetchData()
    return data.userData  // Преобразуем интерфейс
  }
}

const adapter = new APIAdapter(new OldAPI())
console.log(adapter.getUser())  // { name: 'John' }

3. Facade (Фасад)

Упрощенный интерфейс к сложной подсистеме.

class ModuleA {
  init() { console.log('A initialized') }
}

class ModuleB {
  init() { console.log('B initialized') }
}

class ModuleC {
  init() { console.log('C initialized') }
}

// Фасад
class AppFacade {
  constructor() {
    this.modules = [new ModuleA(), new ModuleB(), new ModuleC()]
  }
  
  initializeApp() {
    this.modules.forEach(m => m.init())  // Инициализируем все сразу
  }
}

const app = new AppFacade()
app.initializeApp()

React паттерны

1. Container / Presentational Component

// Presentational — чистый компонент (дуп props)
function UserList({ users, onDelete }) {
  return (
    <ul>
      {users.map(user => (
        <li key={user.id}>
          {user.name}
          <button onClick={() => onDelete(user.id)}>Delete</button>
        </li>
      ))}
    </ul>
  )
}

// Container — логика и state
function UserListContainer() {
  const [users, setUsers] = useState([...])  // Логика
  
  const handleDelete = (id) => {
    setUsers(users.filter(u => u.id !== id))
  }
  
  return <UserList users={users} onDelete={handleDelete} />
}

2. Render Props

class MouseTracker extends React.Component {
  state = { x: 0, y: 0 }
  
  handleMouseMove = (event) => {
    this.setState({ x: event.clientX, y: event.clientY })
  }
  
  render() {
    return (
      <div onMouseMove={this.handleMouseMove}>
        {this.props.children(this.state)}
      </div>
    )
  }
}

// Использование
<MouseTracker>
  {({ x, y }) => <div>Mouse at {x}, {y}</div>}
</MouseTracker>

3. Compound Components

const Tabs = ({ children }) => {
  const [activeTab, setActiveTab] = useState(0)
  
  return (
    <div>
      {React.Children.map(children, (child, idx) => (
        React.cloneElement(child, {
          active: idx === activeTab,
          onClick: () => setActiveTab(idx)
        })
      ))}
    </div>
  )
}

Tabs.Tab = ({ children, active, onClick }) => (
  <button className={active && 'active'} onClick={onClick}>
    {children}
  </button>
)

// Использование
<Tabs>
  <Tabs.Tab>Tab 1</Tabs.Tab>
  <Tabs.Tab>Tab 2</Tabs.Tab>
</Tabs>

JavaScript паттерны

1. Module Pattern

const UserModule = (() => {
  const users = []  // Приватная переменная
  
  return {
    addUser(name) {
      users.push(name)
    },
    getUsers() {
      return [...users]  // Публичный API
    }
  }
})()

UserModule.addUser('John')
console.log(UserModule.getUsers())  // ['John']
// users не доступна снаружи — инкапсуляция!

2. Singleton

const Logger = (() => {
  let instance
  
  return {
    getInstance() {
      if (!instance) {
        instance = { logs: [] }
      }
      return instance
    }
  }
})()

const logger1 = Logger.getInstance()
const logger2 = Logger.getInstance()
console.log(logger1 === logger2)  // true — один экземпляр

3. Factory

function createUser(name, role) {
  return {
    name,
    role,
    getPermissions() {
      if (role === 'admin') return ['read', 'write', 'delete']
      if (role === 'user') return ['read']
      return []
    }
  }
}

const admin = createUser('John', 'admin')
const user = createUser('Jane', 'user')

CSS паттерны

1. BEM (Block Element Modifier)

<div class="button">
  <span class="button__text">Click me</span>
</div>

<style>
.button { padding: 10px; background: blue; }
.button__text { color: white; }
.button--large { padding: 20px; }
.button--disabled { opacity: 0.5; }
</style>

2. Utility-First (Tailwind CSS)

<div class="flex items-center justify-center bg-blue-500 p-4 rounded-lg">
  <span class="text-white font-bold">Button</span>
</div>

Что использую в практике

Часто:

  • Module Pattern (инкапсуляция)
  • Observer (события)
  • Strategy (выбор алгоритма)
  • Container / Presentational (React)
  • Factory (создание объектов)

Периодически:

  • Decorator (логирование, валидация)
  • Adapter (интеграция)
  • Facade (упрощение API)
  • Singleton (одиночный экземпляр)

Редко:

  • Chain of Responsibility (слишком сложно)
  • Visitor (очень специфичный)

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