전체를 관통하는 공통 철학은 개방-폐쇄 원칙(OCP) 이다. 거의 모든 패턴이 “새 기능/타입은 새 클래스로 추가하되, 기존 코드는 수정하지 않는다”를 지향한다는 점이 핵심이다.
1. 생성 패턴
의사결정 흐름: 객체를 만들어야 한다 → 하나만이면 싱글톤 / 서브클래스가 결정하면 팩토리 메서드 / 세트로 묶이면 _추상 팩토리
1.1. 싱글톤
- 인스턴스를 딱 하나만 보장하는 패턴
private 생성자+static 인스턴스+getInstance()세 가지로 구현합니다.- 설정 관리자, 로거, DB 커넥션 풀 등에 쓰이며, 메모리 절약과 일관성이 장점입니다.
- 단, 멀티스레드 환경에서 동시에
instance == null을 통과하면 인스턴스가 두 개 생길 수 있어synchronized나 Eager 초기화가 필요하고, 테스트가 어렵습니다.
1.2. 팩토리 메서드
- 객체 생성을 서브클래스에 위임하는 패턴
- 부모(Creator)는 “어떤 객체를 만들지” 모르고, 자식(ConcreteCreator)이 결정합니다.
- 알림 시스템(Email/Slack/SMS) 등에 적합하며, 새 타입을 추가해도 기존 코드 수정이 없다는(OCP) 게 핵심 장점입니다.
1.3. 추상 팩토리
- 서로 관련된 제품 패밀리 전체를 일관되게 생성하는 패턴
- 공장 하나만 바꾸면 관련 제품 세트가 한꺼번에 교체됩니다.
- (예: Windows 계열 ↔ Mac 계열 UI)
- 제품 계열의 일관성을 보장하지만, 제품 종류가 바뀌면 Factory 인터페이스 자체를 수정해야 합니다.
팩토리 메서드는 제품 하나, 추상 팩토리는 연관된 제품 여러 개를 세트로 생성한다는 점이 차이입니다.
2. 구조 패턴
의사결정 흐름: 기존 코드를 안 건드리고 싶다 → 인터페이스가 안 맞으면 어댑터 / 기능을 추가하면 데코레이터
2.1. 어댑터
- 호환되지 않는 인터페이스를 중간 변환기로 연결하는 패턴
- Adaptee도 Client도 수정 없이 어댑터만 추가합니다(220V 플러그용 돼지코 비유)
- 외부 결제 SDK 연동, 레거시 연결 등에 쓰이며 인터페이스 자체를 바꾼다는 점이 특징입니다.
2.2. 데코레이터
- 기존 객체를 수정하지 않고 겉에 새 기능을 덧씌우는 패턴
- 상속 대신 조합으로 기능을 쌓습니다(아메리카노 + 우유 + 휘핑크림)
- Java I/O가 대표 사례이며, 인터페이스는 그대로 유지하면서 기능만 추가합니다.
- 감싸는 순서에 따라 결과가 달라집니다.
어댑터는 인터페이스를 변환, 데코레이터는 같은 인터페이스를 유지하며 기능을 추가한다는 점이 결정적 차이입니다.
3. 행동 패턴
의사결정 흐름: 행동을 유연하게 → 상태별로 다르면 상태 / 변화를 여러 곳에 알리면 옵서버 컬렉션 순회 → _반복자
3.1. 반복자
- 컬렉션 내부 구조를 몰라도
hasNext()/next()로 순회하게 해주는 패턴 - Java의 for-each가 이 위에서 동작합니다.
- 컬렉션을 교체해도 클라이언트 코드 변경이 없습니다.
3.2. 상태
- 내부 상태가 바뀔 때 행동도 함께 바뀌도록, 거대한 if-else 대신 상태마다 별도 클래스로 분리하는 패턴
- 주문 상태(접수→결제→배송→완료), 자판기 등에 쓰입니다.
- 각 State가 스스로
ctx.setState()로 다음 상태를 전환합니다.
상태 패턴은 State가 스스로 다음 상태로 전환하지만, 전략 패턴은 클라이언트가 직접 전략을 교체한다는 차이가 있습니다.
3.3. 옵서버
- 상태가 바뀌면 구독 중인 모든 객체에 자동으로 알림이 가는 패턴 (“나는 변했어, 알아서 해봐”)
- 주가/코인 알림, 이벤트 UI, MVC의 Model→View 갱신에 쓰입니다.
- 느슨한 결합이 장점이나, 구독 해제를 안 하면 메모리 누수에 주의해야 합니다.