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

Приведи пример использования Open-Closed Principle

2.0 Middle🔥 71 комментариев
#Архитектура и паттерны#ООП

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

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

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

Open-Closed Principle (OCP)

OCP — один из SOLID принципов, который гласит: класс должен быть открыт для расширения, но закрыт для модификации. Это значит, что новую функциональность добавляем через наследование/композицию, не меняя исходный код.

Плохой пример (нарушение OCP)

class PaymentProcessor {
  processPayment(method: string, amount: number) {
    if (method === credit-card) {
      // логика обработки карты
      console.log(`Processing credit card payment: $${amount}`);
    } else if (method === paypal) {
      // логика обработки PayPal
      console.log(`Processing PayPal payment: $${amount}`);
    } else if (method === crypto) {
      // логика обработки крипто
      console.log(`Processing crypto payment: $${amount}`);
    }
  }
}

Проблемы:

  • При добавлении нового способа оплаты нужно менять класс PaymentProcessor
  • Класс нарушает SRP (Single Responsibility) — у него много причин для изменения
  • Сложно тестировать каждый способ отдельно

Хороший пример (соблюдение OCP)

// Интерфейс для платёжных систем
interface PaymentMethod {
  process(amount: number): Promise<void>;
}

// Реализация для кредитной карты
class CreditCardPayment implements PaymentMethod {
  async process(amount: number): Promise<void> {
    console.log(`Processing credit card payment: $${amount}`);
    // специфичная логика для карты
  }
}

// Реализация для PayPal
class PayPalPayment implements PaymentMethod {
  async process(amount: number): Promise<void> {
    console.log(`Processing PayPal payment: $${amount}`);
    // специфичная логика для PayPal
  }
}

// Реализация для крипто
class CryptoPayment implements PaymentMethod {
  async process(amount: number): Promise<void> {
    console.log(`Processing crypto payment: $${amount}`);
    // специфичная логика для крипто
  }
}

// Обработчик платежей (закрыт для модификации)
class PaymentProcessor {
  constructor(private paymentMethod: PaymentMethod) {}

  async processPayment(amount: number): Promise<void> {
    await this.paymentMethod.process(amount);
  }
}

Использование

// Добавляем новый способ оплаты без изменения PaymentProcessor
const creditCardPayment = new CreditCardPayment();
const processor = new PaymentProcessor(creditCardPayment);
await processor.processPayment(100);

// Позже добавляем Apple Pay
class ApplePayPayment implements PaymentMethod {
  async process(amount: number): Promise<void> {
    console.log(`Processing Apple Pay: $${amount}`);
  }
}

const applePayPayment = new ApplePayPayment();
const processor2 = new PaymentProcessor(applePayPayment);
await processor2.processPayment(100);

Преимущества этого подхода

Легко добавлять новые платёжные системы — просто создаём новый класс, реализующий PaymentMethod
PaymentProcessor не меняется — закрыт для модификации
Каждый способ оплаты в отдельном классе — легко тестировать
Соблюдается SRP — каждый класс отвечает за одно
Легко подменять реализации — удобно для dependency injection и мокирования в тестах

Ещё один пример: логирование

interface Logger {
  log(message: string): void;
}

class ConsoleLogger implements Logger {
  log(message: string): void {
    console.log(message);
  }
}

class FileLogger implements Logger {
  log(message: string): void {
    // писать в файл
  }
}

class UserService {
  constructor(private logger: Logger) {}

  createUser(name: string) {
    this.logger.log(`User created: ${name}`);
  }
}

// Меняем логгер без изменения UserService
const service1 = new UserService(new ConsoleLogger());
const service2 = new UserService(new FileLogger());

Итог

OCP достигается через:

  • Интерфейсы/абстракции — определяют контракт
  • Наследование/реализацию — расширяем функциональность
  • Dependency Injection — подставляем нужные реализации
  • Полиморфизм — используем разные реализации прозрачно

Это делает код гибче, понятнее и проще в поддержке.

Приведи пример использования Open-Closed Principle | PrepBro