Какие паттерны проектирования, кроме Singleton, вы использовали в своих проектах?
Sobes Copilot
Получайте ответы в реальном времени
Ответ от нейросети
sobes.tech AI
-
Factory Method: Использовался для создания объектов различных типов внутри родительского класса, делегируя создание подклассам. Это позволяло сделать код более гибким при добавлении новых подтипов.
// Пример Factory Method interface Product { void doSomething(); } class ConcreteProductA implements Product { @Override public void doSomething() { System.out.println("Product A"); } } class ConcreteProductB implements Product { @Override public void doSomething() { System.out.println("Product B"); } } abstract class Creator { public abstract Product factoryMethod(); public void operate() { Product product = factoryMethod(); product.doSomething(); } } class ConcreteCreatorA extends Creator { @Override public Product factoryMethod() { return new ConcreteProductA(); } } class ConcreteCreatorB extends Creator { @Override public Product factoryMethod() { return new ConcreteProductB(); } } -
Observer: Применялся для реализации системы подписки/уведомления, где один объект (издатель) уведомляет множество зависимых объектов (подписчиков) об изменении своего состояния.
// Пример Observer import java.util.ArrayList; import java.util.List; interface Observer { void update(String message); } class ConcreteObserverA implements Observer { @Override public void update(String message) { System.out.println("Observer A received: " + message); } } class ConcreteObserverB implements Observer { @Override public void update(String message) { System.out.println("Observer B received: " + message); } } class Subject { private List<Observer> observers = new ArrayList<>(); private String state; public void attach(Observer observer) { observers.add(observer); } public void detach(Observer observer) { observers.remove(observer); } public void setState(String state) { this.state = state; notifyObservers(); } private void notifyObservers() { for (Observer observer : observers) { observer.update(state); } } } -
Strategy: Использовался для определения семейства алгоритмов, инкапсуляции каждого из них и возможности их взаимозаменяемости. Это позволяет клиенту выбирать алгоритм на лету.
// Пример Strategy interface Strategy { double execute(double a, double b); } class AddStrategy implements Strategy { @Override public double execute(double a, double b) { return a + b; } } class SubtractStrategy implements Strategy { @Override public double execute(double a, double b) { return a - b; } } class MultiplyStrategy implements Strategy { @Override public double execute(double a, double b) { return a * b; } } class Context { private Strategy strategy; public void setStrategy(Strategy strategy) { this.strategy = strategy; } public double executeStrategy(double a, double b) { return strategy.execute(a, b); } } -
Decorator: Применялся для динамического добавления обязанностей к объектам, сохраняя ту же сигнатуру. Это гибкая альтернатива наследованию для расширения функциональности.
// Пример Decorator interface Coffee { String getDescription(); double getCost(); } class SimpleCoffee implements Coffee { @Override public String getDescription() { return "Simple coffee"; } @Override public double getCost() { return 1.0; } } abstract class CoffeeDecorator implements Coffee { protected Coffee decoratedCoffee; public CoffeeDecorator(Coffee decoratedCoffee) { this.decoratedCoffee = decoratedCoffee; } @Override public String getDescription() { return decoratedCoffee.getDescription(); } @Override public double getCost() { return decoratedCoffee.getCost(); } } class MilkDecorator extends CoffeeDecorator { public MilkDecorator(Coffee decoratedCoffee) { super(decoratedCoffee); } @Override public String getDescription() { return decoratedCoffee.getDescription() + ", Milk"; } @Override public double getCost() { return decoratedCoffee.getCost() + 0.5; } } class SugarDecorator extends CoffeeDecorator { public SugarDecorator(Coffee decoratedCoffee) { super(decoratedCoffee); } @Override public String getDescription() { return decoratedCoffee.getDescription() + ", Sugar"; } @Override public double getCost() { return decoratedCoffee.getCost() + 0.2; } } -
Template Method: Использовался для определения скелета алгоритма в суперклассе, позволяя подклассам переопределять конкретные шаги без изменения общей структуры алгоритма.
// Пример Template Method abstract class Game { abstract void initialize(); abstract void startPlay(); abstract void endPlay(); // template method public final void playGame() { initialize(); startPlay(); endPlay(); } } class Chess extends Game { @Override void initialize() { System.out.println("Initializing Chess Game..."); } @Override void startPlay() { System.out.println("Starting Chess Game..."); } @Override void endPlay() { System.out.println("Ending Chess Game..."); } } class Monopoly extends Game { @Override void initialize() { System.out.println("Initializing Monopoly Game..."); } @Override void startPlay() { System.out.println("Starting Monopoly Game..."); } @Override void endPlay() { System.out.println("Ending Monopoly Game..."); } }
Также сталкивался с применением Dependency Injection (часто реализуется фреймворками, но понимание принципов важно).