0% нашли этот документ полезным (0 голосов)
19 просмотров53 страницы

Drip Java Lecture 4

Загружено:

a.sidnevart
Авторское право
© All Rights Reserved
Мы серьезно относимся к защите прав на контент. Если вы подозреваете, что это ваш контент, заявите об этом здесь.
Доступные форматы
Скачать в формате PDF, TXT или читать онлайн в Scribd
0% нашли этот документ полезным (0 голосов)
19 просмотров53 страницы

Drip Java Lecture 4

Загружено:

a.sidnevart
Авторское право
© All Rights Reserved
Мы серьезно относимся к защите прав на контент. Если вы подозреваете, что это ваш контент, заявите об этом здесь.
Доступные форматы
Скачать в формате PDF, TXT или читать онлайн в Scribd

Java Лекция 4

Интерфейсы и паттерны, принципы SOLID. Исключения.


Классы для работы с датами

Денис Син
План лекции

Интерфейсы

Абстрактные классы

SOLID, KISS, YAGNI

Исключения

Классы для работы с датами

Основные паттерны

2
Интерфейс interface Animal {
void makeSound();
• Определение: Интерфейс — это контракт, который }
определяет какие методы должен реализовать
класс. class Dog implements Animal {
@Override
public void makeSound() {
[Link]("Гав!");
}
}

3
Дефолтные и статические interface Vehicle {
default void startEngine() {
методы (Java 8+) [Link]("Двигатель запущен");
• Дефолтные методы: Позволяют добавлять
}
реализацию в интерфейс без нарушения static int getHorsePower() {
существующих классов. return 150;
• Статические методы: Методы, вызываемые через }
имя интерфейса. }

class Car implements Vehicle {} // Использует


startEngine()

4
Множественное interface Flyable {
void fly();
наследование }
• Интерфейсы поддерживают реализацию
нескольких интерфейсов. interface Swimmable {
void swim();
}

class Duck implements Flyable, Swimmable {


@Override
public void fly() { /* ... */ }
@Override
public void swim() { /* ... */ }
}

5
Comparable и Runnable public interface Comparable<T> {
public int compareTo(T o);
• Есть много интерфейсов из стандартной
}
библиотеки
• Runnable – для реализации одно метода запуска public interface Runnable {
какой-то логики /**
• Comparable – для сравнивания объектов * Runs this operation.
*/
void run();
}

6
Comparable

class Student implements Comparable<Student> {


int age;
@Override
public int compareTo(Student other) {
return [Link]([Link], [Link]);
}
}

7
Что такое абстрактный abstract class Shape {
abstract double calculateArea(); // Абстрактный
класс? метод
• Класс, который нельзя инстанцировать. Может
void display() {
содержать абстрактные методы (без реализации) [Link]("Площадь: " + calculateArea());
и обычные методы. }
}

class Circle extends Shape {


double radius;
@Override
double calculateArea() {
return [Link] * radius * radius;
}
}

8
Абстрактные методы
Не имеют тела (реализации).

Должны быть реализованы в подклассах.

9
Абстрактные методы

abstract class DatabaseConnector {


abstract void connect(); // Абстрактный метод
void close() {
[Link]("Соединение закрыто");
}
}

class MySQLConnector extends DatabaseConnector {


@Override
void connect() {
[Link]("Подключено к MySQL");
}
}

10
Конструкторы в abstract class Animal {
String name;
абстрактных классах Animal(String name) { // Конструктор
• Могут иметь конструкторы для инициализации
[Link] = name;
полей. }
• Вызываются при создании подкласса. abstract void sound();
}

class Cat extends Animal {


Cat(String name) {
super(name); // Вызов конструктора
абстрактного класса
}
@Override
void sound() {
[Link](name + " говорит: Мяу!");
}
}

11
Интерфейсы + interface Drawable {
void draw();
абстрактные классы }
• Абстрактный класс может реализовывать
интерфейс. abstract class Figure implements Drawable {
• Подкласс наследует и расширяет abstract void scale(double factor);
функциональность. }

class Square extends Figure {


@Override
public void draw() { /* ... */ }
@Override
void scale(double factor) { /* ... */ }
}

12
Практическое применение abstract class Game {
abstract void initialize(); // Шаги для реализации
абстрактных классов abstract void play();
• Абстрактный класс определяет скелет алгоритма,
abstract void finish();
оставляя реализацию шагов подклассам
final void run() { // Шаблонный метод
initialize();
play();
finish();
}
}

class Chess extends Game {


@Override void initialize() { /* ... */ }
@Override void play() { /* ... */ }
@Override void finish() { /* ... */ }
}

13
Практическое применение абстрактных классов

abstract class PaymentProcessor {


abstract void validate();
abstract void processPayment(double amount);
void logTransaction() {
[Link]("Транзакция записана");
}
}

class PayPalProcessor extends PaymentProcessor {


@Override void validate() { /* ... */ }
@Override void processPayment(double amount) { /* ... */ }
}

14
Number
public abstract class Number implements [Link] {

public Number() {super();}

public abstract int intValue();

public abstract long longValue();

public abstract float floatValue();

public abstract double doubleValue();

public byte byteValue() {


return (byte)intValue();
}

public short shortValue() {


return (short)intValue();
}

private static final long serialVersionUID = -8742448824652078965L;


}
15
Ограничения абстрактных классов
Множественное наследование: Невозможно (Java поддерживает только одиночное)

Состояние: Могут содержать поля, что усложняет иерархию.

Когда выбирать:
• Если нужна общая реализация для группы классов.
• Если требуется состояние (поля).

Интерфейсы: Лучше для определения контракта без привязки к реализации.

16
Итоги Интерфейсы Абстрактные классы

Комбинация: Используйте интерфейсы • Контракт + дефолтные/статические • Общая логика + абстрактные


для гибкости, абстрактные классы — методы. методы.
для повторного использования кода.
• Множественное наследование. • Конструкторы и поля.

17
Полиморфизм // Интерфейс Shape
interface Shape {
• Полиморфизм позволяет использовать одно и то
void draw();
же имя метода для различных классов, где }
реализация этого метода может отличаться.
Например, два разных класса могут иметь метод с // Класс Circle, реализующий интерфейс Shape
одинаковым именем, но выполняющим разные class Circle implements Shape {
действия в зависимости от класса объекта, к @Override
которому он применяется public void draw() {
[Link]("Рисуем круг");
}
}

// Класс Rectangle, реализующий интерфейс Shape


class Rectangle implements Shape {
@Override
public void draw() {
[Link]("Рисуем прямоугольник");
}
}

18
Полиморфизм

abstract class Animal { // Использование полиморфизма:


abstract void sound(); Animal[] animals = {new Dog(), new Cat()};
} for (Animal animal : animals) {
[Link](); // Вызов метода через
class Dog extends Animal { абстрактный класс
@Override }
void sound() {
[Link]("Гав!");
}
}

class Cat extends Animal {


@Override
void sound() {
[Link]("Мяу!");
}
}

19
SOLID
• SOLID — набор правил для создания гибкого и поддерживаемого кода.
• Цель: Упростить масштабирование и уменьшить количество ошибок.
• S — Single Responsibility (Единая ответственность).
• O — Open/Closed (Открытость/Закрытость).
• L — Liskov Substitution (Подстановка Лисков).
• I — Interface Segregation (Разделение интерфейсов).
• D — Dependency Inversion (Инверсия зависимостей).

20
Single responsibility class UserManager {
void createUser(User user) { /* ... */ }
• Класс управляет пользователями, отправляет
void sendEmail(User user, String message) { /* ... */ }
письма и сохраняет в файл — нарушение SRP. void saveToFile(User user) { /* ... */ }
}

21
Single responsibility class UserService { void createUser(User user) { /* ... */ } }
class EmailService { void sendEmail(User user, String
• Итог: Каждый класс отвечает за свою логику.
message) { /* ... */ } }
class FileService { void saveToFile(User user) { /* ... */ } }

22
Open closed class PaymentProcessor {
void process(String type) {
• Класс открыт для расширения, но закрыт для
if ([Link]("PayPal")) { /* ... */ }
изменений. else if ([Link]("CreditCard")) { /* ... */ }
• Добавление нового способа оплаты требует }
изменения кода. }

23
Open closed interface PaymentMethod {
void process();
• Новые способы оплаты добавляются без
}
изменения PaymentProcessor
class PayPal implements PaymentMethod {
@Override
public void process() { /* ... */ }
}

class CreditCard implements PaymentMethod {


@Override
public void process() { /* ... */ }
}

class PaymentProcessor {
void process(String type) {
paymentMethods[type].process()
}
}

24
Принцип L (Liskov Substitution) class Bird {
}
• Иерархия корректна, пингвины не «ломают»
логику. class FlyingBird extends Bird {
void fly() { /* ... */ }
}

class Penguin extends Bird {


}

25
Принцип L (Liskov Substitution) class Bird { void fly() { /* ... */ } }
class Penguin extends Bird {
• Суть: Подклассы должны заменять базовые
@Override void fly() {
классы без сбоев. throw new Error("Пингвины не летают!");
}
}

26
Принцип I (Interface Segregation) interface Worker {
void work();
• Интерфейс заставляет реализовывать ненужные
void eat();
методы. }
class Robot implements Worker {
@Override public void work() { /* ... */ }
@Override public void eat() { /* ... */ } // Робот не
ест!
}

27
Принцип I (Interface Segregation) interface Workable {
void work();
• Клиенты зависят только от нужных методов.
}

interface Eatable {
void eat();
}

class Robot implements Workable {


@Override
public void work() { /* ... */ }
}

28
Принцип D (Dependency class LightBulb {
Inversion) void turnOn() { /* ... */ }
}
• Зависимости строятся на абстракциях, а не на
конкретике.
class Switch {
• Класс Switch зависит от конкретной LightBulb.
private LightBulb bulb = new LightBulb();

void operate() {
[Link]();
}
}

29
interface Switchable {
Принцип D (Dependency void turnOn();
}
Inversion)
• Switch работает с любым устройством через class LightBulb implements Switchable {
интерфейс. @Override
public void turnOn() { /* ... */ }
}

class Fan implements Switchable {


@Override
public void turnOn() { /* ... */ }
}

class Switch {
private Switchable device;

Switch(Switchable device) {
[Link] = device;
}

void operate() {
[Link]();
}
}

30
GRASP
GRASP (General Responsibility Assignment Software Patterns) — набор принципов для распределения
обязанностей между классами.

Цель: Создать гибкую, понятную и легко поддерживаемую архитектуру.

• Information Expert
• Creator
• Controller
• Low Coupling
• High Cohesion

31
Information Expert // Проблема: Где вычислять общую стоимость заказа?
class Order {
List<Product> products;
• Ответственность должна быть назначена классу, // Класс Order знает свои продукты → он и должен
который владеет необходимой информацией. вычислять сумму.
}

class Product {
String name;
double price;
}

// Решение:
class Order {
List<Product> products;
public double getTotalPrice() {
return [Link]().mapToDouble(p -> [Link]).sum();
}
}

32
Creator // Проблема: Кто должен создавать элементы меню?
class Restaurant {
List<MenuItem> menu;
Суть: Класс А должен создавать объекты класса Б, // Ресторан содержит меню → он и создает его элементы.
если: }
• А содержит/агрегирует Б.
class MenuItem {
• А использует Б чаще других.
String name;
double price;
}

// Решение:
class Restaurant {
List<MenuItem> menu = new ArrayList<>();
public void addMenuItem(String name, double price) {
[Link](new MenuItem(name, price));
}
}

33
Controller // Проблема: Обработка нажатия кнопки в UI-классе.
class LoginScreen {
void onLoginButtonClicked() {
Входные запросы системы должны обрабатываться // Проверка логина/пароля, навигация и т.д. → слишком
отдельным классом-«контроллером», а не UI- много логики!
компонентами. }
}

// Решение:
class AuthController {
boolean authenticate(String login, String password) { /* ... */ }
}

class LoginScreen {
AuthController authController = new AuthController();
void onLoginButtonClicked() {
[Link]([Link](),
[Link]());
}
}

34
Low Coupling Слабая // Проблема: Прямая зависимость между классами.
class OrderService {
связанность private MySQLDatabase db; // Жесткая привязка к MySQL
void saveOrder(Order order) {
Минимизируйте зависимости между классами. [Link](order);
}
}

// Решение: Используйте интерфейс!


interface Database {
void save(Object data);
}

class OrderService {
private Database db; // Зависит от абстракции
OrderService(Database db) { [Link] = db; }
}

35
High Cohesion (Высокая // Проблема: Класс делает слишком много.
class UserManager {
связанность) void createUser() { /* ... */ }

Класс должен решать одну задачу, а его методы — void sendEmail() { /* ... */ }
быть логически связаны.
void generateReport() { /* ... */ } // Не относится к управлению
пользователями!
}

// Решение: Разделить на классы.


class UserService {
void createUser() { /* ... */ }
}

class EmailService {
void sendEmail() { /* ... */ }
}

class ReportService {
void generateReport() { /* ... */ }
}

36
Принцип Polymorphism interface SoundMaker {
void makeSound();
(Полиморфизм) }

Используйте полиморфизм для обработки вариаций class Dog implements SoundMaker {


поведения вместо условных конструкций (if/else, @Override
switch). public void makeSound() {
[Link]("Гав!");
}
}

class Cat implements SoundMaker {


@Override
public void makeSound() {
[Link]("Мяу!");
}
}

// Использование:
List<SoundMaker> animals = [Link](new Dog(), new Cat());
[Link](SoundMaker::makeSound);

37
Принцип Pure Fabrication // Проблема: Класс User не должен заниматься сохранением в
БД.
class User {
Создавайте «искусственные» классы для задач, String name;
которые не относятся к предметной области, но void saveToDatabase() { /* ... */ } // Нарушение! Это не
нужны для технической реализации. ответственность User.
}

// Решение: Создать "выдуманный" класс-сервис.


class UserRepository {
void save(User user) { /* ... */ } // Отдельная логика
сохранения.
}

class User {
String name;
// Теперь User содержит только данные.
}

38
Принцип Indirection // Проблема: Прямая связь между PaymentService и PayPal API.
class PaymentService {
private PayPalGateway payPal = new PayPalGateway();
void processPayment() {
Вводите промежуточные компоненты, чтобы [Link]();
уменьшить прямую зависимость между классами. }
}

// Решение: Добавить интерфейс-посредник.


interface PaymentGateway {
void process();
}

class PayPalGateway implements PaymentGateway {


@Override
public void process() { /* ... */ }
}

class PaymentService {
private PaymentGateway gateway;
PaymentService(PaymentGateway gateway) {
[Link] = gateway;
}
void processPayment() {
[Link]();
}
}
39
Исключения в Java — Зачем они int a = 10 / 0; // Программа упадет с ArithmeticException

нужны?
try {
• Ошибки в программе (например, деление на
int a = 10 / 0;
ноль, отсутствие файла) могут привести к
} catch (ArithmeticException e) {
аварийному завершению. [Link]("Деление на ноль запрещено!");
• Исключения позволяют управлять ошибками и }
сохранять контроль над выполнением
программы.

40
Иерархия исключений

41
Обработка исключений (try-catch-finally)

try {
FileReader file = new FileReader("[Link]");
} catch (FileNotFoundException e) {
[Link]("Файл не найден!");
} finally {
[Link]("Блок finally выполнен.");
}

42
Checked exceptions public void readFile() {
try {
FileReader file = new FileReader("[Link]");
} catch (FileNotFoundException e) { // Обработка checked
• Компилятор требует их обработки.
исключения
• Примеры: IOException, SQLException
[Link]("Файл не найден.");
}
} // Если не обработать код не скомпилируется

43
Unchecked exceptions public void calculate() {
int[] arr = {1, 2};
[Link](arr[3]); // ArrayIndexOutOfBoundsException
(unchecked)
• Не требуют явной обработки.
}
• Примеры: ArithmeticException,
ArrayIndexOutOfBoundsException.

44
Создание своих исключений class AgeValidationException extends Exception {
AgeValidationException(String message) {
super(message);
}
• Наследуйтесь от Exception (checked) или
}
RuntimeException (unchecked).
// Использование:
void setAge(int age) throws AgeValidationException {
if (age < 0) throw new AgeValidationException("Возраст не
может быть отрицательным!");
}

45
try with resources try (FileReader file = new FileReader("[Link]")) {
// Работа с файлом
} catch (IOException e) {
[Link]("Ошибка чтения файла.");
• Проблема: Утечка ресурсов (например,
}
незакрытые файлы).
// Ресурс file закрывается автоматически!
• Решение: Автоматическое закрытие ресурсов,
реализующих AutoCloseable.

46
Интерфейс AutoCloseable class DatabaseConnection implements AutoCloseable {
@Override
public void close() {
[Link]("Соединение с БД закрыто.");
• Объекты, которые должны быть закрыты,
}
реализуют метод close().
}

// Использование:
try (DatabaseConnection conn = new DatabaseConnection()) {
// Работа с БД
} // [Link]() вызывается автоматически

47
Множественные исключения в try {
// Код, который может вызвать разные исключения
catch } catch (FileNotFoundException | SQLException e) {
[Link]("Ошибка: " + [Link]());
• Java 7+: Можно перечислять исключения через |. }

48
Best practices
Не игнорируйте исключения:

Используйте специфичные типы исключений:

Логируйте ошибки:

49
Итоги
Исключения делают код устойчивым к ошибкам.

Checked vs Unchecked: Контролируйте обязательную обработку.

Try-with-resources и AutoCloseable упрощают управление ресурсами.

Следуйте лучшим практикам, чтобы код был надежным и читаемым.

50
Зачем нужны классы для // Плохо:
int day = 31;
работы с датами? int month = 12; // Декабрь? А если месяц 0-11?

• Ручное управление датами (дни, месяцы, // Хорошо:


високосные годы) сложно и подвержено LocalDate date = [Link](2024, [Link], 31);
ошибкам.
• Специализированные классы из пакета [Link]
(Java 8+) обеспечивают безопасность и удобство.

51
Основные классы ([Link]) LocalDate date = [Link]();
LocalTime time = [Link](14, 30);
LocalDateTime dateTime = [Link](date, time);
• LocalDate: Дата без времени (год, месяц, день).
• LocalTime: Время без даты (часы, минуты,
секунды).
• LocalDateTime: Дата + время.
• ZonedDateTime: Дата + время + временная зона.

52
Всем больше Java

Вам также может понравиться