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

Какой паттерн использовал бы для изменения поведения объекта в зависимости от времени суток?

2.0 Middle🔥 171 комментариев
#Другое

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

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

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

Паттерны для динамического изменения поведения

Основная проблема

Нужно изменять поведение объекта в 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 по причинам:

  1. Простота — легко понять и реализовать
  2. Гибкость — легко добавлять новые стратегии
  3. Тестируемость — каждую стратегию можно тестировать отдельно
  4. SOLID — соответствует Open/Closed и Single Responsibility принципам

Если нужны автоматические переходы, то добавить Time-based выбор стратегии через Enum или LocalDateTime.

Заключение

Для изменения поведения в зависимости от времени суток используй Strategy Pattern. Это даст тебе гибкость, чистоту кода и простоту тестирования.

Какой паттерн использовал бы для изменения поведения объекта в зависимости от времени суток? | PrepBro