Что такое паттерн State?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Паттерн 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 делает код более гибким, понятным и удобным в поддержке, особенно когда число состояний растёт.