Что такое паттерн State?

Ответ

Паттерн State (Состояние) — это поведенческий паттерн проектирования, который позволяет объекту изменять своё поведение при изменении его внутреннего состояния. Создаётся впечатление, что объект изменил свой класс.

Зачем он нужен? Чтобы избавиться от больших условных операторов (if/switch), которые проверяют состояние объекта, и инкапсулировать логику каждого состояния в отдельный класс.

Пример на Java:

// Интерфейс состояния
interface State {
    void handle(Context context);
}

// Конкретное состояние A
class ConcreteStateA implements State {
    public void handle(Context context) {
        System.out.println("Обработка в состоянии A. Переход в состояние B.");
        context.setState(new ConcreteStateB());
    }
}

// Конкретное состояние B
class ConcreteStateB implements State {
    public void handle(Context context) {
        System.out.println("Обработка в состоянии B. Переход в состояние A.");
        context.setState(new ConcreteStateA());
    }
}

// Контекст, который хранит состояние
class Context {
    private State state;

    public Context(State initialState) {
        this.state = initialState;
    }

    public void setState(State state) {
        this.state = state;
    }

    // Запрос, который делегируется текущему состоянию
    public void request() {
        state.handle(this);
    }
}

// Использование
public class Main {
    public static void main(String[] args) {
        Context context = new Context(new ConcreteStateA());
        context.request(); // Переключится в StateB
        context.request(); // Вернется в StateA
    }
}

Преимущества:

  • Убирает монолитные условные конструкции.
  • Упрощает добавление новых состояний (принцип открытости/закрытости).
  • Концентрирует код, связанный с определённым состоянием, в одном классе.

Недостатки:

  • Может привести к созданию множества небольших классов.
  • Избыточен, если состояний мало и они редко меняются.

Ответ 18+ 🔞

Смотри, вот есть у тебя объект. И он, сука, как хамелеон, блядь — сегодня он один, завтра другой, поведение меняется в зависимости от какого-то внутреннего флага, состояния там, ёпта.

И что делает обычный распиздяй? Правильно, нагородит if-ов или switch-ей на триста строк, которые проверяют: «а если состояние равно «ХУЙНЯ_1», то сделай так, а если «ХУЙНЯ_2», то сделай эдак». И каждый раз, когда надо добавить новое поведение, ты лезешь в эту пиздопроёбину, рискуя всё сломать. Терпения ноль, ебать!

А паттерн State подходит и говорит: «Да не ёбись ты так! Давай каждое состояние вынесем в отдельный класс, пусть он сам знает, что делать и куда переходить дальше». И объект-контекст будет просто дергать метод у текущего состояния, а оно уже само разберется — хуяк, и переключит контекст на следующее, если надо.

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

// Это типа контракт для всех состояний. «Мужик, если ты состояние — умей обработать запрос».
interface State {
    void handleRequest(VendingMachine machine);
}

// Состояние «Готов к работе, деньги принимаю, ёба!»
class ReadyState implements State {
    public void handleRequest(VendingMachine machine) {
        System.out.println("Готов к работе. Жду твои деньги, нищеброд.");
        // Допустим, деньги кинули — переводим автомат в состояние выбора товара
        machine.setState(new SelectingState());
    }
}

// Состояние «Выбирай уже, нахуй, товар, я жду!»
class SelectingState implements State {
    public void handleRequest(VendingMachine machine) {
        System.out.println("Товар выбран. Сейчас всё выдадим, не дёргайся.");
        // Товар выдали — автомат снова готов
        machine.setState(new ReadyState());
    }
}

// Сам автомат — контекст
class VendingMachine {
    private State state; // Текущее состояние — вот эта самая хитрая жопа

    public VendingMachine() {
        this.state = new ReadyState(); // Начинаем с готовности
    }

    // Вот этот метод — главный. Нажали кнопку — делегируем всё текущему состоянию
    public void pressButton() {
        state.handleRequest(this);
    }

    // Сеттер для состояния. Позволяет состояниям самим переключать автомат
    public void setState(State state) {
        this.state = state;
        System.out.println("Состояние автомата поменялось на: " + state.getClass().getSimpleName());
    }
}

// Использование
public class Main {
    public static void main(String[] args) {
        VendingMachine machine = new VendingMachine();
        machine.pressButton(); // Перешёл в SelectingState
        machine.pressButton(); // Вернулся в ReadyState
    }
}

Что хорошего, блядь?

  • Условия нахуй. Никаких if (state == READY) { ... } else if (state == SELECTING) { ... }. Вся логика спрятана в классах-состояниях. Чистота, мать его.
  • Легко расширять. Надо новое состояние «ЗАЖИМ_ДЕНЕГ»? Создаёшь класс MoneyStuckState, реализуешь метод, и впихиваешь его в логику перехода из того состояния, где деньги могут застрять. Не надо ковырять весь остальной код.
  • Всё на своих местах. Код, отвечающий за выдачу товара, лежит в классе DispensingState, а не размазан по десяти методам контекста.

А где подвох, ёпта?

  • Классов дофига. Если состояний реально много (как у того же автомата: «нет денег», «деньги есть», «выбор», «выдача», «сдача», «ошибка»), то классов будет овердохуища. Но это, как правило, лучше, чем спагетти из условий.
  • Стрельба из пушки по воробьям. Если у тебя объект имеет всего два состояния и они меняются раз в жизни — не городи огород, иди нахуй со своим паттерном. Сделай boolean-флаг и пару if-ов, не умничай.

Короче, State — это когда твой объект должен вести себя как шлюха, постоянно меняя свою сущность, и ты хочешь, чтобы это было управляемо, а не через пень-колоду.