State — это поведенческий паттерн, который позволяет объекту менять своё поведение при изменении внутреннего состояния. Извне кажется, что объект сменил свой класс.
Простыми словами: банкомат ведёт себя по-разному в зависимости от состояния: ожидание карты → ввод PIN → выбор операции. Одна и та же кнопка делает разные вещи.
▪️ Пример:
Заказ в интернет-магазине проходит через состояния: Новый → Оплачен → Доставляется → Завершён. В каждом состоянии допустимы разные действия.
// Интерфейс состояния
interface OrderState {
void pay(OrderContext order);
void ship(OrderContext order);
void deliver(OrderContext order);
}
// Контекст
class OrderContext {
private OrderState state;
public OrderContext() {
this.state = new NewOrderState();
}
public void setState(OrderState state) {
this.state = state;
System.out.println("Статус → " + state.getClass().getSimpleName());
}
public void pay() { state.pay(this); }
public void ship() { state.ship(this); }
public void deliver() { state.deliver(this); }
}
class NewOrderState implements OrderState {
public void pay(OrderContext order) {
System.out.println("Оплата принята");
order.setState(new PaidOrderState());
}
public void ship(OrderContext order) {
System.out.println("Нельзя отправить неоплаченный заказ");
}
public void deliver(OrderContext order) {
System.out.println("Заказ ещё не отправлен");
}
}
class PaidOrderState implements OrderState {
public void pay(OrderContext order) {
System.out.println("Уже оплачен");
}
public void ship(OrderContext order) {
System.out.println("Заказ передан курьеру");
order.setState(new ShippedOrderState());
}
public void deliver(OrderContext order) {
System.out.println("Заказ ещё не отправлен");
}
}
class ShippedOrderState implements OrderState {
public void pay(OrderContext order) {
System.out.println("Уже оплачен");
}
public void ship(OrderContext order) {
System.out.println("Уже в пути");
}
public void deliver(OrderContext order) {
System.out.println("Заказ доставлен!");
order.setState(new DeliveredOrderState());
}
}
class DeliveredOrderState implements OrderState {
public void pay(OrderContext o) { System.out.println("Завершён"); }
public void ship(OrderContext o) { System.out.println("Завершён"); }
public void deliver(OrderContext o) { System.out.println("Уже доставлен"); }
}
// Использование
OrderContext order = new OrderContext();
order.pay(); // Оплата принята → PaidOrderState
order.ship(); // Передан курьеру → ShippedOrderState
order.deliver(); // Доставлен! → DeliveredOrderState
order.pay(); // Завершён
▪️ Когда использовать
— Объект ведёт себя по-разному в зависимости от состояния
— Много if/switch по статусу — признак, что нужен State
— Количество состояний может расти
▪️ State vs Strategy
— Strategy: клиент выбирает алгоритм
— State: объект сам переключает поведение при смене состояния
▪️ Минус
Избыточен, если состояний всего 2–3 и переходы простые.
🐸 Библиотека собеса по Java
#patterns