public class Singleton{
// 생성자는 외부에서 호출못하게 private 으로 지정
private Singleton() {}
// 인스턴스를 생성하고 반환하는 정적 메서드 제공
// (synchronized로 멀티스레드 안전성 보장)
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
public class Singleton {
// 클래스 로딩 시 인스턴스를 미리 생성
private static final Singleton instance = new Singleton();
// 생성자는 외부에서 호출못하게 private 으로 지정
private Singleton() {}
// 인스턴스를 반환하는 정적 메서드 제공
public static Singleton getInstance() {
return instance;
}
}
출처 : [https://refactoring.guru/ko/design-patterns/factory-method]
// 1. 제품 인터페이스
interface Car {
void drive();
}
// 2. 구체적인 제품 클래스들
class Sedan implements Car {
@Override
public void drive() {
System.out.println("Sedan 주행 중...");
}
}
class SUV implements Car {
@Override
public void drive() {
System.out.println("SUV 주행 중...");
}
}
// 3. 팩토리 클래스
class CarFactory {
// 팩토리 메서드
public Car createCar(String carType) {
if (carType == null) {
return null;
}
if (carType.equalsIgnoreCase("Sedan")) {
return new Sedan();
} else if (carType.equalsIgnoreCase("SUV")) {
return new SUV();
}
return null;
}
}
// 4. 클라이언트 코드
public class Main {
public static void main(String[] args) {
CarFactory carFactory = new CarFactory();
// Sedan 생성
Car sedan = carFactory.createCar("Sedan");
sedan.drive(); // Sedan 주행 중...
// SUV 생성
Car suv = carFactory.createCar("SUV");
suv.drive(); // SUV 주행 중...
}
}
출처 : [https://velog.io/@kyle/디자인-패턴-전략패턴이란]
클래스 수 증가
알고리즘 선택의 책임이 클라이언트에게 있음
예시 코드
// 결제 전략 인터페이스
interface PaymentStrategy {
void pay(int amount);
}
// 카드 결제 전략
class CreditCardStrategy implements PaymentStrategy {
private String cardNumber;
public CreditCardStrategy(String cardNumber) {
this.cardNumber = cardNumber;
}
@Override
public void pay(int amount) {
System.out.println(amount + "원을 카드로 결제합니다. 카드 번호: " + cardNumber);
}
}
// 페이팔 결제 전략
class PayPalStrategy implements PaymentStrategy {
private String email;
public PayPalStrategy(String email) {
this.email = email;
}
@Override
public void pay(int amount) {
System.out.println(amount + "원을 페이팔로 결제합니다. 페이팔 계정: " + email);
}
}
// Context 클래스 (결제 처리)
class ShoppingCart {
private PaymentStrategy paymentStrategy;
public void setPaymentStrategy(PaymentStrategy paymentStrategy) {
this.paymentStrategy = paymentStrategy;
}
public void checkout(int amount) {
paymentStrategy.pay(amount);
}
}
// 클라이언트 코드
public class Main {
public static void main(String[] args) {
ShoppingCart cart = new ShoppingCart();
// 카드로 결제
cart.setPaymentStrategy(new CreditCardStrategy("1234-5678-9876-5432"));
cart.checkout(5000); // 5000원을 카드로 결제합니다.
// 페이팔로 결제
cart.setPaymentStrategy(new PayPalStrategy("user@example.com"));
cart.checkout(10000); // 10000원을 페이팔로 결제합니다.
}
}
출처 : [https://medium.com/@jiyeeon1208/옵저버-패턴-observer-pattern-d4368116e279]
복잡성 증가 → 많은 옵저버 등록 시 알림 시간 증가 및 코드 복잡
옵저버가 많아질수록, 상태를 변경할 때 어떤 옵저버가 어떻게 반응할지 예측 어려움
알림을 보낼 때 성능 저하가 발생할 수 있음
예시 코드
// 1. 옵저버 인터페이스 (Observer)
interface Observer {
void update(String message);
}
// 2. 주제 인터페이스 (Subject)
interface Subject {
void addObserver(Observer observer);
void removeObserver(Observer observer);
void notifyObservers();
}
// 3. 구체적인 주제 (ConcreteSubject)
class NewsAgency implements Subject {
private List<Observer> observers = new ArrayList<>();
private String news;
public void setNews(String news) {
this.news = news;
notifyObservers(); // 뉴스가 업데이트되면 옵저버들에게 알림
}
@Override
public void addObserver(Observer observer) {
observers.add(observer);
}
@Override
public void removeObserver(Observer observer) {
observers.remove(observer);
}
@Override
public void notifyObservers() {
for (Observer observer : observers) {
observer.update(news);
}
}
}
// 4. 구체적인 옵저버 (ConcreteObserver)
class NewsSubscriber implements Observer {
private String name;
public NewsSubscriber(String name) {
this.name = name;
}
@Override
public void update(String message) {
System.out.println(name + " received news: " + message);
}
}
// 5. 클라이언트 코드
public class Main {
public static void main(String[] args) {
NewsAgency newsAgency = new NewsAgency();
NewsSubscriber subscriber1 = new NewsSubscriber("Subscriber 1");
NewsSubscriber subscriber2 = new NewsSubscriber("Subscriber 2");
newsAgency.addObserver(subscriber1);
newsAgency.addObserver(subscriber2);
newsAgency.setNews("Breaking News: New Observer Pattern Example!");
}
}
출처 : [https://refactoring.guru/ko/design-patterns/proxy]
응답 속도 지연
복잡성 증가
예시 코드
// 1. 주제 인터페이스 (공통 인터페이스)
interface Service {
void request();
}
// 2. 실제 객체 (RealSubject)
class RealService implements Service {
@Override
public void request() {
System.out.println("실제 서비스 요청 처리");
}
}
// 3. 프록시 객체 (Proxy)
class ProxyService implements Service {
private RealService realService;
@Override
public void request() {
if (realService == null) {
realService = new RealService(); // 실제 객체 생성 (지연 초기화)
}
System.out.println("프록시에서 접근 제어 처리 중...");
realService.request(); // 실제 서비스 요청
}
}
// 4. 클라이언트 코드
public class Main {
public static void main(String[] args) {
Service service = new ProxyService(); // 프록시 객체 사용
service.request(); // 프록시를 통해 실제 객체에 접근
}
}
출처 : [https://velog.io/@jw01987/MVC-패턴]
모델, 뷰, 컨트롤러로 이뤄진 디자인 패턴
예시 코드
// Model (데이터 및 로직)
class Model {
private String data;
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
}
// View (UI)
class View {
public void display(String data) {
System.out.println("Displaying: " + data);
}
}
// Controller (사용자 요청 처리 및 데이터 전달)
class Controller {
private Model model;
private View view;
public Controller(Model model, View view) {
this.model = model;
this.view = view;
}
public void setData(String data) {
model.setData(data); // 모델에 데이터 설정
}
public void updateView() {
view.display(model.getData()); // 뷰에 데이터 전달
}
}
// 클라이언트 코드
public class MVCPatternExample {
public static void main(String[] args) {
Model model = new Model();
View view = new View();
Controller controller = new Controller(model, view);
controller.setData("Hello, MVC Pattern!"); // 모델 데이터 설정
controller.updateView(); // 뷰 업데이트
}
}