Ответ
Часто используемые паттерны в Java:
-
Singleton (Одиночка): Гарантирует существование только одного экземпляра класса. Важно учитывать потокобезопасность.
public class ThreadSafeSingleton { private static volatile ThreadSafeSingleton instance; private ThreadSafeSingleton() {} public static ThreadSafeSingleton getInstance() { if (instance == null) { synchronized (ThreadSafeSingleton.class) { if (instance == null) { instance = new ThreadSafeSingleton(); } } } return instance; } } -
Factory Method (Фабричный метод): Определяет интерфейс для создания объекта, но оставляет подклассам решение о том, какой класс инстанцировать.
public interface Notification { void notifyUser(); } public class EmailNotification implements Notification { @Override public void notifyUser() { System.out.println("Sending an email..."); } } public abstract class NotificationService { // Фабричный метод public abstract Notification createNotification(); public void sendNotification() { Notification notification = createNotification(); notification.notifyUser(); } } -
Observer (Наблюдатель): Определяет зависимость "один ко многим", чтобы при изменении состояния одного объекта все зависящие от него объекты уведомлялись автоматически. Реализован в Java через
java.util.Observableиjava.util.Observer(устарели) или через собственную реализацию.
Также активно применяю:
- Builder: Для пошагового создания сложных объектов (особенно полезен с Lombok
@Builder). - Strategy: Для инкапсуляции семейства алгоритмов и их взаимозаменяемости.
- Decorator: Для динамического добавления новой функциональности объектам (реализуется через композицию).
- Adapter: Для обеспечения совместной работы классов с несовместимыми интерфейсами.
Ответ 18+ 🔞
Слушай, а паттерны-то в Java — это вообще отдельная песня, ебать мои старые костыли! Как будто архитекторы, блядь, сговорились и придумали целый язык для того, чтобы объяснять одно и то же, но разными, ёпта, умными словами. Берёшь обычную идею, обзываешь её на латыни — и вот тебе, сука, паттерн, продавай книжки!
Вот, например, Singleton (Одиночка). Ну что это такое, если не глобальная переменная, но в дорогом костюме, блядь? "Гарантируем один экземпляр!" — орут они. А на деле вся история — это один сплошной геморрой с потокобезопасностью. Смотри, как народ изгаляется, чтобы эту самую одну штуку создать:
public class ThreadSafeSingleton {
private static volatile ThreadSafeSingleton instance; // volatile, ёпта, чтоб память не кэшировала!
private ThreadSafeSingleton() {} // Конструктор спрятали, хитрая жопа!
public static ThreadSafeSingleton getInstance() {
if (instance == null) { // Первая проверка, чтоб зря в synchronized не лезть
synchronized (ThreadSafeSingleton.class) { // А вот тут уже серьёзно, блядь
if (instance == null) { // Вторая проверка, на случай если кто проскочил
instance = new ThreadSafeSingleton(); // И только тут рожаем
}
}
}
return instance;
}
}
Двойная проверка, volatile, synchronized... Да я один такой экземпляр, блядь, за это время вручную двадцать напишу! Но нет, так "правильно", так "безопасно". Чистый овердохуища церемоний для одной сущности.
Дальше — Factory Method (Фабричный метод). Вообще шедевр, ёперный театр! Смысл-то простой, как три копейки: не вызывай new напрямую, позови какую-нибудь функцию, пусть она тебе объект сделает. Но обрядили это в такую абстракцию, что волосы дыбом!
public interface Notification {
void notifyUser();
}
public class EmailNotification implements Notification {
@Override
public void notifyUser() {
System.out.println("Sending an email..."); // Тррр-тррр, письмо полетело
}
}
public abstract class NotificationService {
// Самый тот самый фабричный метод! Абстрактный, блядь!
public abstract Notification createNotification();
public void sendNotification() {
Notification notification = createNotification(); // О, волшебство! Не знаю что создаст, но создаст!
notification.notifyUser();
}
}
И что мы имеем? Родительский класс (NotificationService) говорит: "Я отправлю уведомление, но вот что именно я буду отправлять — это, сынок, твои проблемы, переопределяй метод createNotification". И сидит потом программист, чешет репу: "Так... у меня EmailNotificationService или SmsNotificationService? А, бля, да похуй, главное шаблон соблюсти!"
Ну и вишенка на торте — Observer (Наблюдатель). Это когда один объект (субъект) орет на всю деревню: "Йоу, я изменился!", а куча других объектов (наблюдателей) ему в ответ: "О, спасибо, кэп, теперь и мы что-нибудь сделаем!". В Java даже родные Observable/Observer были, да такие кривые, что их все забили и пишут свои велосипеды. Суть-то проще пареной репы: список подписчиков и метод notifyAll. Но нет, надо же это "паттерном" обозвать!
Из остального, что постоянно юзаю, в рот меня чих-пых:
- Builder — спасение от конструкторов с десятью параметрами. Особенно с Lombok'ом — аннотацию поставил и живи не тужи. Красота, а не паттерн.
- Strategy — когда у тебя куча похожих алгоритмов, и ты хочешь тыкать их в объект, как патроны в обойму. Включил нужный — и поехали.
- Decorator — мощнейшая штука для добавления функциональности. Обернул один объект в другой, потом в третий — и получил слоёный пирог из поведения. Главное — не переборщить, а то будет не декоратор, а манда с ушами.
- Adapter — классика жанра. Есть старая кривая библиотека, а тебе надо, чтобы она работала с твоим красивым кодом. Пишешь прослойку-адаптер, который превращает кривые вызовы в нормальные. Работа грязная, но кто-то же должен её делать!
В общем, паттерны — это как специи. Посыпал немного — код ароматнее и понятнее стал. Переборщил — есть невозможно, одна горечь и абстракция. Чувство меры, ёпта, главное!