객체지향 디자인 패턴은 소프트웨어 설계에서 반복적으로 발생하는 문제를 해결하는 일반적인 설계 템플릿입니다.
즉, 객체지향 프로그래밍(OOP)의 원칙을 활용하여 유지보수성과 확장성이 좋은 코드 구조를 설계하는 방법입니다.
📌 객체지향 설계 원칙(SOLID)과 밀접한 관련이 있음!
SOLID 원칙:
- Single Responsibility Principle (단일 책임 원칙)
- Open/Closed Principle (개방-폐쇄 원칙)
- Liskov Substitution Principle (리스코프 치환 원칙)
- Interface Segregation Principle (인터페이스 분리 원칙)
- Dependency Inversion Principle (의존 역전 원칙)
객체지향 디자인 패턴은 목적(사용 목적)에 따라 크게 3가지로 나눌 수 있습니다.
객체의 생성 과정을 효율적으로 관리하는 패턴입니다.
✅ 1.1 싱글턴 패턴 (Singleton)
하나의 클래스에 단 하나의 인스턴스만 생성되는 것을 보장하는 패턴.
전역적으로 접근 가능한 객체가 필요할 때 사용.
🔹 예제 (Java)
public class Singleton {
private static Singleton instance;
private Singleton() {} // private 생성자로 외부 인스턴스 생성 차단
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
✔ 사용 예시
✅ 1.2 팩토리 패턴 (Factory Method)
객체 생성을 서브클래스에서 담당하도록 하는 패턴.
객체 생성을 캡슐화하여 코드 의존성을 줄임.
🔹 예제 (Java)
// 인터페이스
interface Animal {
void makeSound();
}
// 구현체
class Dog implements Animal {
public void makeSound() {
System.out.println("멍멍!");
}
}
class Cat implements Animal {
public void makeSound() {
System.out.println("야옹!");
}
}
// 팩토리 클래스
class AnimalFactory {
public static Animal createAnimal(String type) {
if (type.equals("Dog")) return new Dog();
else if (type.equals("Cat")) return new Cat();
return null;
}
}
// 사용 예시
public class Main {
public static void main(String[] args) {
Animal animal = AnimalFactory.createAnimal("Dog");
animal.makeSound(); // 출력: 멍멍!
}
}
✔ 사용 예시
클래스 및 객체 간의 관계를 설정하는 패턴입니다.
✅ 2.1 어댑터 패턴 (Adapter)
기존 코드와 새로운 코드 간의 인터페이스를 맞춰주는 패턴.
서로 다른 인터페이스를 사용하는 클래스를 호환 가능하게 만듦.
🔹 예제 (Java)
// 기존 코드 (Old API)
class LegacyPrinter {
void printOld(String text) {
System.out.println("Old Printer: " + text);
}
}
// 새 인터페이스
interface Printer {
void print(String text);
}
// 어댑터 클래스
class PrinterAdapter implements Printer {
private LegacyPrinter legacyPrinter;
public PrinterAdapter(LegacyPrinter legacyPrinter) {
this.legacyPrinter = legacyPrinter;
}
public void print(String text) {
legacyPrinter.printOld(text);
}
}
// 사용 예시
public class Main {
public static void main(String[] args) {
Printer printer = new PrinterAdapter(new LegacyPrinter());
printer.print("Hello World!"); // 출력: Old Printer: Hello World!
}
}
✔ 사용 예시
객체 간의 책임 분배 및 협력 방식을 정의하는 패턴입니다.
✅ 3.1 옵저버 패턴 (Observer)
객체 간의 1:N 의존성을 정의하여 한 객체의 상태 변화가 여러 객체에 자동으로 전달되도록 하는 패턴.
(이벤트 리스너, 알림 시스템 등에서 사용)
🔹 예제 (Java)
import java.util.ArrayList;
import java.util.List;
// 옵저버 인터페이스
interface Observer {
void update(String message);
}
// 구독자(Observer) 구현체
class User implements Observer {
private String name;
public User(String name) {
this.name = name;
}
public void update(String message) {
System.out.println(name + "님에게 알림: " + message);
}
}
// 주제(Subject)
class NewsChannel {
private List<Observer> observers = new ArrayList<>();
public void addObserver(Observer observer) {
observers.add(observer);
}
public void notifyObservers(String message) {
for (Observer observer : observers) {
observer.update(message);
}
}
}
// 사용 예시
public class Main {
public static void main(String[] args) {
NewsChannel channel = new NewsChannel();
Observer user1 = new User("홍길동");
Observer user2 = new User("이순신");
channel.addObserver(user1);
channel.addObserver(user2);
channel.notifyObservers("새로운 뉴스가 도착했습니다!");
}
}
✔ 사용 예시
객체지향 디자인 패턴은 소프트웨어 설계의 유지보수성과 확장성을 높이는 데 필수적입니다.
📌 요약
- 생성 패턴 → 객체 생성 방식 최적화 (ex. 싱글턴, 팩토리)
- 구조 패턴 → 객체 간 관계 최적화 (ex. 어댑터)
- 행동 패턴 → 객체 간 역할/책임 조정 (ex. 옵저버)
🛠 실제 개발에서 어떻게 활용될까?
- 웹 애플리케이션: MVC 패턴 (옵저버 패턴 활용)
- 게임 개발: 싱글턴 패턴(게임 매니저, 설정 객체)
- 디자인 시스템: 팩토리 패턴 (UI 요소 생성)
객체지향 설계를 더 깊이 이해하고 싶은 경우, SOLID 원칙과 함께 디자인 패턴을 적용해보는 것이 좋습니다