Какой паттерн проектирования вы считаете наиболее полезным и часто применяете?

Ответ

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

Почему он полезен:

  • Устраняет условные операторы: Заменяет громоздкие if-else или switch на полиморфизм.
  • Соблюдает OCP (Open/Closed Principle): Новые алгоритмы добавляются без изменения существующего кода клиента.
  • Упрощает тестирование: Каждую стратегию можно тестировать изолированно.

Пример реализации в Java:

// 1. Общий интерфейс стратегии
public interface PaymentStrategy {
    void pay(double amount);
}

// 2. Конкретные стратегии
public class CreditCardPayment implements PaymentStrategy {
    private String cardNumber;
    public CreditCardPayment(String cardNumber) { this.cardNumber = cardNumber; }
    @Override
    public void pay(double amount) {
        System.out.println("Paid " + amount + " using Credit Card: " + cardNumber);
    }
}

public class PayPalPayment implements PaymentStrategy {
    private String email;
    public PayPalPayment(String email) { this.email = email; }
    @Override
    public void pay(double amount) {
        System.out.println("Paid " + amount + " using PayPal: " + email);
    }
}

// 3. Контекст, использующий стратегию
public class ShoppingCart {
    private PaymentStrategy paymentStrategy;
    private double totalAmount = 0;

    public void setPaymentStrategy(PaymentStrategy strategy) {
        this.paymentStrategy = strategy;
    }

    public void checkout() {
        if (paymentStrategy == null) {
            throw new IllegalStateException("Payment strategy not set");
        }
        paymentStrategy.pay(totalAmount);
    }
}

// 4. Использование
public class Main {
    public static void main(String[] args) {
        ShoppingCart cart = new ShoppingCart();
        cart.setPaymentStrategy(new CreditCardPayment("1234-5678-9012-3456"));
        cart.checkout(); // Вызывает оплату через кредитную карту

        cart.setPaymentStrategy(new PayPalPayment("user@example.com"));
        cart.checkout(); // Легко переключились на PayPal
    }
}

Где применяется: Сортировка (разные компараторы), валидация, алгоритмы скидок, выбор способа доставки, форматирование данных.

Ответ 18+ 🔞

Так, слушай, смотри, есть одна штука, которая в программировании как глоток воздуха после трёх литров пива — паттерн Стратегия. Суть в чём, блядь? Берёшь кучу похожих алгоритмов, которые только мечтают, чтобы их в if-else на три экрана завернули, и просто делаешь их взаимозаменяемыми фигурками. Красота, ёпта!

Ну и нахуя это надо, спросишь?

  • Избавляешься от этой ебаной кучи условий: Вместо того чтобы каждый раз мозг ломать над switch, который уже на втором этаже, просто подсовываешь нужную стратегию. Полиморфизм, детка, он всё стерпит.
  • Не трогаешь старый код, когда надо новое: Принцип "открыт-закрыт" в действии. Хочешь добавить новый способ оплаты "криптой жопой мира"? Пожалуйста! Пишешь новый класс и подсовываешь. Старый код даже не чихнёт.
  • Тестируется проще пареной репы: Каждую стратегию можно отъебашивать юнит-тестами по отдельности, не трогая весь остальной цирк.

Смотри, как это выглядит в Java, на примере оплаты:

// 1. Это наш контракт, наша основа основ. Все стратегии будут его ебашить.
public interface PaymentStrategy {
    void pay(double amount);
}

// 2. А вот и сами стратегии. Конкретные пацаны.
public class CreditCardPayment implements PaymentStrategy {
    private String cardNumber;
    public CreditCardPayment(String cardNumber) { this.cardNumber = cardNumber; }
    @Override
    public void pay(double amount) {
        System.out.println("Оплачено " + amount + " руб. картой: " + cardNumber);
    }
}

public class PayPalPayment implements PaymentStrategy {
    private String email;
    public PayPalPayment(String email) { this.email = email; }
    @Override
    public void pay(double amount) {
        System.out.println("Оплачено " + amount + " руб. через PayPal: " + email);
    }
}

// 3. А это наш главный по тарелкам — контекст. Он использует стратегию, но сам нихуя не знает, какая именно.
public class ShoppingCart {
    private PaymentStrategy paymentStrategy;
    private double totalAmount = 100.0; // Допустим, набрали на сотку

    // Сюда подсовываем стратегию
    public void setPaymentStrategy(PaymentStrategy strategy) {
        this.paymentStrategy = strategy;
    }

    public void checkout() {
        if (paymentStrategy == null) {
            throw new IllegalStateException("Э, ты стратегию-то выбери, а потом уже чекауться!");
        }
        paymentStrategy.pay(totalAmount); // Всё, делегировали работу
    }
}

// 4. Ну и как этим пользоваться, блядь
public class Main {
    public static void main(String[] args) {
        ShoppingCart cart = new ShoppingCart();

        // Решил картой платить
        cart.setPaymentStrategy(new CreditCardPayment("1234-5678-9012-3456"));
        cart.checkout(); // "Оплачено 100.0 руб. картой: 1234..."

        // Передумал, хочу через PayPal
        cart.setPaymentStrategy(new PayPalPayment("user@example.com"));
        cart.checkout(); // "Оплачено 100.0 руб. через PayPal: user..."
        // И ни одного if! Вообще! Пиздец как красиво.
    }
}

Где эту хуйню применить можно? Да везде, где есть выбор! Сортировка разная, валидация форм, расчёт скидок ("для своих", "для распиздяев", "для оптовиков"), выбор службы доставки ("СДЭК", "Почта России, прости господи"). В общем, везде, где голова болит от условий.