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

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

2.0 Middle🔥 151 комментариев
#SOLID и паттерны проектирования

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

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

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

Паттерн State (Состояние)

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

Проблема

Когда у объекта есть несколько состояний и поведение меняется в зависимости от текущего состояния, код часто переполняется условными операторами:

public class Document {
    private String state;
    
    public void publish() {
        if ("draft".equals(state)) {
            // логика публикации черновика
        } else if ("moderation".equals(state)) {
            // логика публикации из модерации
        } else if ("published".equals(state)) {
            // уже опубликовано
        }
    }
}

Это нарушает принцип Open/Closed (легко ломается при добавлении новых состояний), усложняет код и затрудняет тестирование.

Решение

Паттерн State предлагает создать отдельные классы для каждого состояния и делегировать действия текущему состоянию:

Интерфейс состояния:

public interface DocumentState {
    void publish(Document document);
    void reject(Document document);
    void archive(Document document);
}

Конкретные состояния:

public class DraftState implements DocumentState {
    @Override
    public void publish(Document document) {
        System.out.println("Документ отправлен на модерацию");
        document.setState(new ModerationState());
    }
    
    @Override
    public void reject(Document document) {
        throw new IllegalStateException("Нельзя отклонить черновик");
    }
    
    @Override
    public void archive(Document document) {
        document.setState(new ArchivedState());
    }
}

public class ModerationState implements DocumentState {
    @Override
    public void publish(Document document) {
        System.out.println("Документ опубликован");
        document.setState(new PublishedState());
    }
    
    @Override
    public void reject(Document document) {
        System.out.println("Документ отклонён");
        document.setState(new DraftState());
    }
    
    @Override
    public void archive(Document document) {
        throw new IllegalStateException("Нельзя архивировать документ в модерации");
    }
}

public class PublishedState implements DocumentState {
    @Override
    public void publish(Document document) {
        throw new IllegalStateException("Документ уже опубликован");
    }
    
    @Override
    public void reject(Document document) {
        throw new IllegalStateException("Нельзя отклонить опубликованный документ");
    }
    
    @Override
    public void archive(Document document) {
        System.out.println("Документ архивирован");
        document.setState(new ArchivedState());
    }
}

Контекст (основной класс):

public class Document {
    private DocumentState state;
    private String title;
    
    public Document(String title) {
        this.title = title;
        this.state = new DraftState();
    }
    
    public void publish() {
        state.publish(this);
    }
    
    public void reject() {
        state.reject(this);
    }
    
    public void archive() {
        state.archive(this);
    }
    
    public void setState(DocumentState newState) {
        this.state = newState;
    }
    
    public DocumentState getState() {
        return state;
    }
}

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

Document doc = new Document("Моя статья");
doc.publish();   // Документ отправлен на модерацию
doc.publish();   // Документ опубликован
doc.archive();   // Документ архивирован

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

  • Избегаем множественных условных операторов — логика каждого состояния в отдельном классе
  • Single Responsibility — каждое состояние отвечает только за себя
  • Open/Closed — можно легко добавлять новые состояния без изменения существующего кода
  • Лучшая организация кода — состояния логически разделены
  • Упрощённое тестирование — каждое состояние тестируется отдельно

Когда использовать

  • Поведение объекта зависит от состояния и должно меняться во время выполнения
  • В коде много условных операторов (if/switch), которые зависят от состояния
  • Операции имеют большие условные блоки

Реальные примеры

  • Управление состоянием заказа (новый, оплачено, отправлено, доставлено)
  • Игровые системы (персонаж может быть в состояниях: ждёт, движется, атакует, умирает)
  • Медиаплеер (стоп, воспроизведение, пауза)
  • Управление доступом (неавторизирован, авторизирован, администратор)

Паттерн State делает код более гибким, понятным и удобным в поддержке, особенно когда число состояний растёт.

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