Какой паттерн использовал бы для изменения поведения объекта в зависимости от времени суток?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Паттерны для динамического изменения поведения
Основная проблема
Нужно изменять поведение объекта в runtime в зависимости от состояния (времени суток). Это классический случай для использования design patterns. Рассмотрю несколько подходов.
Решение 1: Strategy Pattern (рекомендуемое)
Strategy Pattern — это паттерн, который позволяет выбирать алгоритм в runtime. Это идеальный выбор для данной задачи.
// Интерфейс стратегии
public interface BehaviorStrategy {
void execute();
String describe();
}
// Конкретные стратегии
public class DayBehavior implements BehaviorStrategy {
@Override
public void execute() {
System.out.println("[DAY] Активная работа, яркое освещение");
System.out.println("[DAY] Высокая производительность");
}
@Override
public String describe() {
return "Дневное поведение (6:00 - 18:00)";
}
}
public class EveningBehavior implements BehaviorStrategy {
@Override
public void execute() {
System.out.println("[EVENING] Переход в режим экономии");
System.out.println("[EVENING] Приглушённое освещение");
}
@Override
public String describe() {
return "Вечернее поведение (18:00 - 22:00)";
}
}
public class NightBehavior implements BehaviorStrategy {
@Override
public void execute() {
System.out.println("[NIGHT] Минимальное потребление энергии");
System.out.println("[NIGHT] Ночной режим активен");
}
@Override
public String describe() {
return "Ночное поведение (22:00 - 6:00)";
}
}
// Класс с изменяемым поведением
public class SmartDevice {
private BehaviorStrategy currentStrategy;
private final String name;
public SmartDevice(String name) {
this.name = name;
this.currentStrategy = new DayBehavior(); // Поведение по умолчанию
}
// Изменяем поведение в runtime
public void setStrategy(BehaviorStrategy strategy) {
this.currentStrategy = strategy;
System.out.println("[" + name + "] Переключено на: " + strategy.describe());
}
public void performAction() {
System.out.println("\n[" + name + "] выполняет действие:");
currentStrategy.execute();
}
}
// Использование
public class Main {
public static void main(String[] args) {
SmartDevice lamp = new SmartDevice("Умная лампа");
// День
lamp.setStrategy(new DayBehavior());
lamp.performAction();
// Вечер
lamp.setStrategy(new EveningBehavior());
lamp.performAction();
// Ночь
lamp.setStrategy(new NightBehavior());
lamp.performAction();
}
}
Преимущества:
- Лёгко добавить новые стратегии (Open/Closed Principle)
- Чистое разделение ответственности
- Легко тестировать каждую стратегию
Решение 2: State Pattern (альтернатива)
State Pattern похож на Strategy, но подразумевает, что сам объект управляет переходами между состояниями.
// Интерфейс состояния
public interface TimeOfDayState {
void handle(SmartLamp lamp);
String getStateName();
}
public class DayState implements TimeOfDayState {
@Override
public void handle(SmartLamp lamp) {
System.out.println("[ДЕНЬ] Максимальная яркость: 100%");
lamp.setBrightness(100);
}
@Override
public String getStateName() {
return "Day";
}
}
public class NightState implements TimeOfDayState {
@Override
public void handle(SmartLamp lamp) {
System.out.println("[НОЧЬ] Ночной режим: 10%");
lamp.setBrightness(10);
}
@Override
public String getStateName() {
return "Night";
}
}
public class SmartLamp {
private TimeOfDayState currentState;
public SmartLamp() {
this.currentState = new DayState();
}
public void setState(TimeOfDayState state) {
this.currentState = state;
}
public void operate() {
currentState.handle(this);
}
public void setBrightness(int level) {
System.out.println("Яркость установлена на: " + level + "%");
}
}
Отличие от Strategy:
- State: сам объект управляет переходами между состояниями
- Strategy: клиент явно выбирает стратегию
Решение 3: Time-based Strategy (лучше для real-world)
Реальное решение, которое я бы использовал в production:
// Enum для времени суток
public enum TimeOfDay {
EARLY_MORNING(6, 10),
MORNING(10, 12),
AFTERNOON(12, 18),
EVENING(18, 22),
NIGHT(22, 6);
private final int startHour;
private final int endHour;
TimeOfDay(int startHour, int endHour) {
this.startHour = startHour;
this.endHour = endHour;
}
public static TimeOfDay getCurrentTimeOfDay() {
int currentHour = LocalDateTime.now().getHour();
for (TimeOfDay period : values()) {
if (period == NIGHT) {
// Ночь: с 22 до 6 утра (переход через полночь)
if (currentHour >= 22 || currentHour < 6) {
return NIGHT;
}
} else if (currentHour >= period.startHour && currentHour < period.endHour) {
return period;
}
}
return MORNING; // По умолчанию
}
}
// Интерфейс поведения
public interface TimeAwareBehavior {
void execute(TimeOfDay timeOfDay);
boolean isApplicable(TimeOfDay timeOfDay);
}
// Реализации для разных времён
public class NightModeBehavior implements TimeAwareBehavior {
@Override
public void execute(TimeOfDay timeOfDay) {
System.out.println("Ночной режим активирован");
System.out.println("- Минимальная яркость");
System.out.println("- Фильтр синего света");
System.out.println("- Бесшумная работа");
}
@Override
public boolean isApplicable(TimeOfDay timeOfDay) {
return timeOfDay == TimeOfDay.NIGHT;
}
}
public class DayModeBehavior implements TimeAwareBehavior {
@Override
public void execute(TimeOfDay timeOfDay) {
System.out.println("Дневной режим активирован");
System.out.println("- Максимальная яркость");
System.out.println("- Стандартная цветовая температура");
System.out.println("- Полная производительность");
}
@Override
public boolean isApplicable(TimeOfDay timeOfDay) {
return timeOfDay == TimeOfDay.AFTERNOON || timeOfDay == TimeOfDay.MORNING;
}
}
// Адаптивное устройство
public class AdaptiveDevice {
private final List<TimeAwareBehavior> behaviors = new ArrayList<>();
private final String deviceName;
public AdaptiveDevice(String deviceName) {
this.deviceName = deviceName;
}
public void registerBehavior(TimeAwareBehavior behavior) {
behaviors.add(behavior);
}
public void adapt() {
TimeOfDay currentTime = TimeOfDay.getCurrentTimeOfDay();
System.out.println("\n[" + deviceName + "] Текущее время суток: " + currentTime);
for (TimeAwareBehavior behavior : behaviors) {
if (behavior.isApplicable(currentTime)) {
behavior.execute(currentTime);
}
}
}
}
// Использование
public class Main {
public static void main(String[] args) {
AdaptiveDevice smartPhone = new AdaptiveDevice("Смартфон");
smartPhone.registerBehavior(new DayModeBehavior());
smartPhone.registerBehavior(new NightModeBehavior());
// Адаптируется в зависимости от текущего времени
smartPhone.adapt();
}
}
Решение 4: Decorator Pattern (для дополнительного поведения)
Если нужно добавлять поведение, а не заменять его:
public abstract class BehaviorDecorator {
protected BehaviorStrategy wrappedBehavior;
public BehaviorDecorator(BehaviorStrategy behavior) {
this.wrappedBehavior = behavior;
}
public abstract void execute();
}
public class EnergySavingDecorator extends BehaviorDecorator {
public EnergySavingDecorator(BehaviorStrategy behavior) {
super(behavior);
}
@Override
public void execute() {
System.out.println("[ENERGY SAVING] Снижение потребления энергии...");
wrappedBehavior.execute();
System.out.println("[ENERGY SAVING] Завершено");
}
}
// Использование
BehaviorStrategy nightBehavior = new NightBehavior();
BehaviorStrategy withEnergySaving = new EnergySavingDecorator(nightBehavior);
withEnergySaving.execute();
Сравнение подходов
| Паттерн | Когда использовать | Сложность |
|---|---|---|
| Strategy | Выбор алгоритма в runtime | Простой |
| State | Объект управляет переходами | Средняя |
| Time-based | Адаптация к условиям | Средняя |
| Decorator | Добавление поведения | Сложный |
Мой рекомендуемый подход
Для задачи с временем суток я выбрал бы Strategy Pattern по причинам:
- Простота — легко понять и реализовать
- Гибкость — легко добавлять новые стратегии
- Тестируемость — каждую стратегию можно тестировать отдельно
- SOLID — соответствует Open/Closed и Single Responsibility принципам
Если нужны автоматические переходы, то добавить Time-based выбор стратегии через Enum или LocalDateTime.
Заключение
Для изменения поведения в зависимости от времени суток используй Strategy Pattern. Это даст тебе гибкость, чистоту кода и простоту тестирования.