Зарегистрируйтесь, чтобы продолжить обучение

Паттерны (продолжение) Java: Основы ООП

Паттерн "Стратегия"

Стратегия – это паттерн проектирования, который определяет семейство схожих алгоритмов и помещает каждый из них в собственный класс, после чего алгоритмы можно взаимозаменять прямо во время исполнения программы

double price = 100.83
Discounter christmasDiscounter = new ChristmasDiscounter();
Discounter eightMarchDiscounter = new EightMarchDiscounter();
List<Discounter> discounters = new ArrayList<>();

discounters.add(christmasDiscounter);
discounters.add(eightMarchDiscounter);

for (Discounter discounter : discounters) {
    if (discounter.checkCondition()) {
        discounter.applyDiscount(price);
    }
}

Интерфейс Discounter

public interface Discounter {
    double applyDiscount(double price);
    boolean checkCondition();
}

Классы стратегий

public class ChristmasDiscounter implements Discounter {

    @Override
    public double applyDiscount(double price) {
        System.out.println("ChristmasDiscounter has been applied");
        return price * 0.5;
    }

    @Override
    public boolean checkCondition() {
        Calendar calendar = Calendar.getInstance();
        long currentDate = calendar.getTimeInMillis();
        calendar.set(Calendar.MONTH, 11);
        calendar.set(Calendar.DAY_OF_MONTH, 25);
        long christmasDay = calendar.getTimeInMillis();
        calendar.set(Calendar.DAY_OF_MONTH, 1);
        long startChristmasDiscountDay = calendar.getTimeInMillis();

        return currentDate >= startChristmasDiscountDay && currentDate <= christmasDay;
    }
}
public class EightMarchDiscounter implements Discounter {

    @Override
    public double applyDiscount(double price) {
        System.out.println("EightMarchDiscounter has been applied");
        return price * 0.75;
    }

    @Override
    public boolean checkCondition() {
        Calendar calendar = Calendar.getInstance();
        long currentDate = calendar.getTimeInMillis();
        calendar.set(Calendar.MONTH, 2);
        calendar.set(Calendar.DAY_OF_MONTH, 8);
        long eightMarchDay = calendar.getTimeInMillis();

        calendar.set(Calendar.DAY_OF_MONTH, 1);
        long startEightMarcDiscountDay = calendar.getTimeInMillis();

        return currentDate >= startEightMarcDiscountDay && currentDate <= eightMarchDay;
    }
}

Паттерн "Наблюдатель"

Наблюдатель – это паттерн проектирования, который создает механизм подписки, позволяющий одним объектам следить и реагировать на события, происходящие в других объектах

WeatherDataCenter weatherDataCenter = new WeatherDataCenter();
WeatherDataReceiver weatherDataReceiver = new WeatherDataReceiver();
weatherDataCenter.registerObserver(weatherDataReceiver);

WeatherData weatherData = new WeatherData();
weatherData.setTemperature(29.3);
weatherData.setPressure(760.3);

weatherDataCenter.notifyObservers(weatherData);

Классы WeatherDataCenter и WeatherDataReceiver

public class WeatherDataCenter implements Observable<WeatherData> {

    private List <Observer<WeatherData>> observers = new ArrayList<>();
    private WeatherData weatherData;

    @Override
    public void notifyObservers(WeatherData weatherData) {
        this.weatherData = weatherData;

        for (Observer observer : observers) {
            observer.update(weatherData);
        }
    }

    public void registerObserver(Observer<WeatherData> observer) {
        observers.add(observer);
    }

    public void removeObserver(Observer<WeatherData> observer) {
        observers.remove(observer);
    }
}
public class WeatherDataReceiver implements Observer<WeatherData> {

    private WeatherData weatherData;

    @Override
    public void update(WeatherData model) {
        this.weatherData = model;
        System.out.println(
            "Weather data has been updated: " + weatherData
        );
    }
}

Интерфейсы

public interface Observable<T> {
    void registerObserver(Observer<T> observer);
    void removeObserver(Observer<T> observer);
    void notifyObservers(T data);
}
public interface Observer<T> {
    void update(T model);
}

Класс WeatherData

@Getter
@Setter
@ToString
public class WeatherData {
    private double temperature;
    private double pressure;
}

Паттерн State

// Example.java
public class Example {
    public static void main(String[] args) {
        Car car2 = new Car();
        // Обращение к методам происходит через первоначальное получение состояния
        car2.getState().go();

        // start car
        car2.getState().start();
        car2.getState().go();

        car2.getState().lock();

        State state = car2.getState();
        if (state != null) {
            state.stop();
        }

        car2.getState().lock();
    }
}
// Car.java
import exercise.state.impl.LockedState;

public class Car {
    // Должна быть связь с классом состояния
    private State state;

    public Car() {
        this.state = new LockedState(this);
    }

    public State getState() {
        return state;
    }

    public void setState(State state) {
        this.state = state;
    }
}
// State.java
// Интерфейс состояния, каждое состояние должно реализовать его
public interface State {
    void go();
    void stop();
    void start();
    void lock();
}
// DriveState.java
public class DriveState implements State {
    // Должна быть связь с классом Car
    private Car car;

    public DriveState(Car car) {
        this.car = car;
    }

    @Override
    public void go() {
        System.out.println("I have gone yet.");
    }

    @Override
    public void stop() {
        System.out.println("Okey, I will stop");
        this.car.setState(new StartState(this.car));
    }

    @Override
    public void start() {
        System.out.println("I have been started.");
    }

    @Override
    public void lock() {
        System.out.println("I can't be locked.");
    }
}
// StartState.java
public class StartState implements State {
    private Car car;

    public StartState(Car car) {
        this.car = car;
    }

    @Override
    public void go() {
        Car car = this.car;
        car.setState(new DriveState(car));
        System.out.println("Okey, I can do it.");
    }

    @Override
    public void stop() {
        System.out.println("Okey, I can be stopped.");
    }

    @Override
    public void start() {
        System.out.println("I have been started.");
    }

    @Override
    public void lock() {
        Car c = this.car;
        c.setState(new LockedState(c));
        System.out.println("Car has been locked.");
    }


}

// LockedState.java
public class LockedState implements State {
    private Car car;

    public LockedState(Car car) {
        this.car = car;
    }

    @Override
    public void go() {
        System.out.println("I have been locked. I can't go before you do not start me.");
    }

    @Override
    public void stop() {
        System.out.println("I have been locked. It means that I stopped.");
    }

    @Override
    public void start() {
        Car c = this.car;
        c.setState(new StartState(c));
        System.out.println("Car has been started.");
    }

    @Override
    public void lock() {
        System.out.println("Car has been locked.");
    }
}

Дополнительные материалы

  1. Паттерны без привязки к языку

Аватары экспертов Хекслета

Остались вопросы? Задайте их в разделе «Обсуждение»

Вам ответят команда поддержки Хекслета или другие студенты

Для полного доступа к курсу нужен базовый план

Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.

Получить доступ
1000
упражнений
2000+
часов теории
3200
тестов

Открыть доступ

Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно

  • 130 курсов, 2000+ часов теории
  • 1000 практических заданий в браузере
  • 360 000 студентов
Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»

Наши выпускники работают в компаниях:

Логотип компании Альфа Банк
Логотип компании Aviasales
Логотип компании Yandex
Логотип компании Tinkoff
Рекомендуемые программы
профессия
от 25 000 ₸ в месяц
Разработка приложений на языке Java
10 месяцев
с нуля
Старт 23 января

Используйте Хекслет по-максимуму!

  • Задавайте вопросы по уроку
  • Проверяйте знания в квизах
  • Проходите практику прямо в браузере
  • Отслеживайте свой прогресс

Зарегистрируйтесь или войдите в свой аккаунт

Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»
Изображение Тото

Задавайте вопросы, если хотите обсудить теорию или упражнения. Команда поддержки Хекслета и опытные участники сообщества помогут найти ответы и решить задачу