У цій статті ми з вами розглянемо патерни проєктування в Java — їх значення, важливість і застосування в реальних проектах. Не хвилюйтеся, ми будемо поступово розглядати все і тримати пояснення простими.
Патерни проєктування — це ефективні рішення для часто зустрічаються проблем в програмуванні. Вони допомагають створювати чистий, зручний для підтримки код і роблять командну роботу простішою завдяки спільній мові розробників.
Ми розглянемо три основні типи патернів: Творчі (Creational), Структурні (Structural) та Поведенкові (Behavioral). Кожен тип буде розглянуто через приклади з детальними поясненнями.
Якщо ви вже знайомі з Java і розумієте основи об’єктно-орієнтованого програмування, то можете сміливо почати. Поїхали!
Фото: Amélie Mourichon на Unsplash
Прототип — це творчий патерн проєктування, який дозволяє копіювати існуючі об’єкти без залежності вашого коду від їх класів.
Проблема
Уявіть, що ви розробляєте додаток, в якому потрібно створити кілька екземплярів складного об’єкта, наприклад, Документ
, що містить різноманітні властивості: текст, зображення та форматування. Кожен раз створювати такий екземпляр з нуля може бути надто ресурсоємно. Ви хочете уникнути витрат на створення нового об’єкта, копіюючи вже існуючий екземпляр і вносячи незначні зміни.
Рішення
Патерн Прототип допомагає вирішити цю проблему, дозволяючи створювати нові об’єкти шляхом копіювання існуючих. Це особливо корисно, коли створення об’єктів передбачає дорогі операції, як-то введення/виведення (I/O), виклики до баз даних або складні ініціалізації.
Структура
- Інтерфейс Прототип: Оголошує метод для клонування самого себе.
- Конкретний Прототип: Реалізує інтерфейс Прототип і надає логіку клонування.
- Клієнт: Використовує інтерфейс Прототип для клонування об’єктів, замість того, щоб створювати їх вручну.
Застосування
Цей патерн корисний, коли:
- Створення нових екземплярів класу є занадто затратним.
- Потрібно уникнути витрат на створення об’єктів з нуля.
- Необхідно створювати багато об’єктів із схожим станом, але з незначними відмінностями.
Це особливо корисно, коли об’єкти складно створити або вони мають багато налаштувань.
Як реалізувати
- Визначте Інтерфейс Прототип: Створіть інтерфейс, який містить метод для клонування об’єкта.
public interface Prototype {
Prototype clone();
}
- Створіть Конкретний Прототип: Реалізуйте інтерфейс і визначте, як здійснюється клонування. Ви можете вибрати між поверхневим копіюванням або глибоким копіюванням, залежно від складності об’єкта.
import java.util.Date;
public class Document implements Prototype {
private String text;
private Date creationDate;
public Document(String text, Date creationDate) {
this.text = text;
this.creationDate = creationDate;
}
@Override
public Prototype clone() {
return new Document(this.text, this.creationDate);
}
public void setText(String text) {
this.text = text;
}
public String getText() {
return text;
}
public Date getCreationDate() {
return creationDate;
}
@Override
public String toString() {
return "Document{" +
"text='" + text + '\'' +
", creationDate=" + creationDate +
'}';
}
}
Якщо клас містить змінні посилання (наприклад, Date), для безпеки використовуйте глибоке копіювання: new Date(this.creationDate.getTime())
- Використання Прототипа: Клієнтський код використовує метод
clone()
для створення копії об’єкта замість того, щоб створювати новий вручну.
public class PrototypeDemo {
public static void main(String[] args) {
Document original = new Document("Original text", new Date());
Document cloned = (Document) original.clone();
System.out.println(original == cloned); // Виведе: false
System.out.println(original.getText());
System.out.println(cloned.getText());
}
}
Використовуємо Інтерфейс Прототип для Клонування Об’єктів: клієнтський код клонує об’єкт замість створення нового з нуля.
public class PrototypeApp {
public static void main(String[] args) {
Document originalDocument = new Document("Original Text", new Date());
System.out.println("Original Document: " + originalDocument);
Document clonedDocument = (Document) originalDocument.clone();
clonedDocument.setText("Cloned Text");
System.out.println("Cloned Document: " + clonedDocument);
}
}
Чи використовує це Spring Framework, і якщо так, то як?
Так, Spring активно підтримує патерн Прототип через свої обсяги бінів.
За замовчуванням Spring використовує синглтон-обсяг для бінів. Однак, якщо бін має обсяг прототипа, Spring створює новий екземпляр щоразу, коли цей бін запитується з контейнера.
Ось як можна визначити бін з обсягом прототипа:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
@Configuration
public class AppConfig {
@Bean
@Scope("prototype")
public Document document() {
return new Document("Prototype Text", new Date());
}
}
Кожного разу, коли цей бін інжектується або запитується, Spring повертає новий екземпляр:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class DocumentService {
@Autowired
private Document document;
public void printDocument() {
System.out.println(document);
}
}
️ Spring керує лише створенням прототипів. Життєві цикли, такі як @PreDestroy, не будуть автоматично викликані для бінів з обсягом прототипа.
Переваги та недоліки
Переваги:
- Ефективність: Уникає дорогого створення об’єктів, покращуючи продуктивність.
- Гнучкість: Клоновані об’єкти можна змінювати незалежно.
- Спрощене створення: Централізує логіку створення об’єктів через клонування.
Недоліки:
- Складність: Потребує уважного підходу, особливо для глибокого копіювання.
- Виклики глибокого копіювання: Забезпечення повного дублювання складних об’єктів може бути важким.
- Ризики мутабельності: Поверхневе копіювання може призвести до спільного використання змінних полів, що може викликати помилки.
- Можливість неправильного використання: Невірне застосування може призвести до проблем з відслідковуванням спільних посилань.
Використовуючи патерн Прототип, ви зможете ефективно створювати варіації складних об’єктів, зберігаючи чистоту і повторне використання механізму створення. Цей підхід надзвичайно потужний, коли його застосовують разом з обсягом прототипа в Spring або при створенні фреймворків, що вимагають клонування об’єктів для налаштування або шаблонної логіки.
Github репозиторій: https://github.com/LuisSalas94/design_patterns
Дуже дякую, що прочитали мою статтю до кінця! Сподіваюся, що вона була корисною і ви отримали нові цінні відомості.
Якщо вам сподобалося, будь ласка, поділіться статтею з друзями та колегами — я буду дуже вдячний!
Також, якщо ви хочете глибше зануритися в ці теми, не соромтеся підписатися на мій канал на YouTube для більше підручників і порад.
Ще раз дякую за вашу підтримку!
💖 Скажіть мені 👋!
Фернандо Салас
YouTube: youtube.com/@CodeWithFernando?sub_confirmation=1
Email: [email protected]
LinkedIn: https://www.linkedin.com/in/luisfernandosalasgave/
GitHub: https://github.com/LuisSalas94
Medium: https://medium.com/@luisfernandosalasg
Перегляньте інші мої статті:
- Патерн програмування: Циклічне сортування
- Патерн програмування: Два вказівники
- Патерн програмування: Сковзаюче вікно
- 3 нетехнічні книги, які зроблять вас кращим програмістом
- Покрокова інструкція: Розробка API магазину книг з Spring Boot та MySQL для операцій CRUD
- Ефективна передача даних в REST API: Глибоке занурення в патерн DTO з Spring Boot та MySQL
- Забезпечення цілісності даних в Spring Boot: Обробка винятків і стратегії валідації даних
- Повний посібник по Spring Data JPA: Розбудова додатку магазину книг з нуля — Частина I
- Повний посібник по Spring Data JPA: Розбудова додатку магазину книг з нуля — Частина II
- Повний посібник по Spring Data JPA: Розбудова додатку магазину книг з нуля — Частина III
- Розробка повного стеку для системи управління студентами з React і Spring Boot
- Вивчення патернів програмування: Погляд всередину патерну Стратегії
- Вивчення патернів програмування: Погляд всередину патерну Спостерігач
- Всеосяжний посібник з тестування Spring Boot за допомогою JUnit і Mockito
- Вивчення патернів програмування: Погляд всередину патерну Декоратор
- Принципи SOLID у Java: Основи чистого та зручного коду
- Розуміння основ ООП: Асоціація, Агрегація та Композиція
- Всеосяжний посібник з пагінації та сортування в Spring Boot додатках
Перекладено з: Creational Patterns: Prototype