✅ 디자인 패턴의 정의
디자인 패턴이란 자주 발생하는 설계 상의 문제를 해결하기 위한 반복적인 해법입니다.
GoF의 정의에 의하면, 일반적인 설계문제를 해결하기 위하여 짜인 상호 협력하는 객체들과 클래스들에 대한 기술입니다.
즉, 디자인 패턴은 UML을 일일이 그리지 않아도 특정 코드 전체를 설명할 수 있는 단어를 의미합니다.
중요한 것은 디자인 패턴의 이름만 보고 패턴을 연상할 수 있어야 합니다.
예를 들어, 디자인 패턴을 사용하지 않고 팀원들끼리 소통한다면 특정 문제를 해결하기 위해 다음과 같이 말해야 합니다.
"이러한 메서드를 가진 클래스를 만들고, 이 클래스를 상속하는 서브 클래스를 만들어서... "
문장이 길어지며 서로 이해하기도 어려울 것입니다. 디자인 패턴을 사용한다면, 위 문장을 간단한 한 마디로 얘기할 수 있습니다.
OO 패턴을 사용하자!
위 한 마디로 팀원들은 각자 머릿속에 문제 해결법을 떠올릴 수 있을 것입니다.
UML: Unfied Modeling Language로, 프로그램을 다이어그램화한 것
🏷 디자인 패턴의 역사
디자인 패턴의 개념은 건축에서의 패턴으로부터 왔습니다. Christopher Alexander는 패턴으로 창문의 높이, 건물의 층 수 등을 설명할 수 있다고 설명했다.
그리고 소프트웨어 개발 영역에서 디자인 패턴은 책 "Design Patterns: Elements of Reusable Object-Oriented Software"이 1995년 출간되면서 유명해졌습니다.
이 책을 출간한 네 명 Erich Gamma, Richard Helm, Ralph Johnson, John Vlisisides 은 Gang Of Four로 불렸으며 줄여서 GoF입니다.
🏷 디자인 패턴을 사용하는 이유
디자인 패턴의 장점은 한 마디로 코드가 더 견고해지고 재사용이 용이해진다는 것입니다.
- 재사용이 쉽다
- 융통성 있어 확장이 쉽다
- 유지보수가 쉬워진다.
- 팀 내에서 효과적인 커뮤니케이션이 가능하다.
- SOLID 원칙을 잘 지킬 수 있다. 대부분의 디자인 패턴은 SOLID 원칙을 기반으로 설계되었다.
✅ 디자인 패턴(Design Pattern) vs. 프레임워크(Framework)
디자인 패턴은 설계를 재활용하는 것에 초점을 둡니다. 반면 프레임워크는 세부 설계와 구현에 초점을 둡니다.
이는 디자인 패턴에서는 세부 설계와 구현이 바뀔 수 있다는 것입니다.
설계를 재활용한다는 것은 어떤 역할의 클래스가 필요하고, 클래스끼리는 어떻게 연결되어야 하는지 등이 정해져 있다는 것입니다.
디자인 패턴은 특정 문제를 해결하기 위한 솔루션이고, 프레임워크는 여러 가지 문제들에 대해 디자인 패턴을 적용하여 개발된 뼈대 구조입니다.
그렇다면, 디자인 패턴은 패턴마다 해결하고자 하는 문제 영역이 있다는 의미입니다.
✅ 디자인 패턴의 특징
1️⃣ 관점(view) - 패턴을 나타내는 방식
- 정적: 패턴을 이루는 클래스들과 이들의 정적인 관계를 표현 ex) 클래스 다이어그램
- 동적: 기능이 어떤 순서로 호출되고 실행되는지 표현 ex) 순차 다이어그램, 상태 다이어그램
2️⃣ 수준(level) - 패턴의 분석
- 추상적 수준(abstract): 패턴의 핵심을 기술
- 구체적 수준(concrete): 자세한 패턴 실체를 나타내는 수준
3️⃣ 역할(role) - 패턴 사용에서의 역할
- 디자인 패턴 애플리케이션 자체 : 패턴을 이용해서 무언가를 표현한 것
- 디자인 패턴을 사용하는 클라이언트 : 패턴을 이용하는 입장
- 초기화 또는 제어하는 셋업 코드 : 객체를 실제 만들어주는 부분
✅ 디자인 패턴의 종류
GoF에서 23개의 설계 패턴을 3가지 유형으로 분류하여 카테고리화해 놓았습니다.
1️⃣ 생성(Creational) 패턴
객체의 생성에 관한 패턴입니다.
- Abstract Factory (추상 팩토리) : 다양한 구성 요소 별로 객체의 집합을 생성해야 할 때
- Prototype (프로토타입) : 기존 객체의 복사를 통해 새로운 객체를 생성하고 싶을 때
- Singleton (싱글톤) : 동시에 객체의 인스턴스가 하나만 존재하게 하고 싶을 때
- Factory Method (팩토리 메서드) : 생성할 클래스의 종류를 결정하는 시점을 뒤로 미루고 싶을 때
- Builder (빌더) : 복잡한 객체를 단계별로 생성하고 싶을 때
2️⃣ 구조(Structural) 패턴
객체의 구조와 관련된 패턴입니다.
- Adapter (어댑터) : 호환되지 않는 인터페이스를 바꾸어 같이 협력할 수 있게 하고 싶을 때
- Bridge (브리지) : 구현부와 추상층을 분리하여 독립적으로 확장이 가능하게 하고 싶을 때
- Composite (컴포지트) : 개별 객체와 객체의 묶음을 같은 방식으로 취급하고 싶을 때
- Decorator (데코레이터) : 기존 객체를 수정하지 않고도 새로운 기능을 추가하고 싶을 때
- Flyweight : 객체의 부담을 줄이기 위하여 작은 객체들로 나누고 공유하고 싶을 때
- Facade (퍼사드) : 서브 시스템의 인터페이스로 통합된 인터페이스를 제공하고 싶을 때
- Proxy (프록시) : 실제 객체가 필요한 시점까지 객체의 생성을 연기하고 객체가 생성된 것처럼 동작하고 싶을 때
3️⃣ 행위(Behavioral) 패턴
메시지 교환 관련으로, 객체의 행위에 관련된 패턴입니다.
- Chainof Responsibility (책임 연쇄) : 특정 요청을 여러 객체에서 처리해야 할 때
- Command (커맨드) : 요청을 객체의 형태로 캡슐화해야 할 때
- Iterator (반복자) : 객체집합에 있는 요소들을 내부 표현에 구애받지 않고 순차적으로 접근하고 싶을 때
- Mediator(중재자) : 연관된 행위와 객체 자체를 분리하기 위하여 중간에 중재하는 클래스를 도입하고 싶을 때
- Memento(메멘토) : 객체의 구현 부분을 공개하지 않으면서 해당 객체의 이전 상태를 저장하고 복원하고 싶을 때
- Observer(옵서버) : 1대다의 객체 관계에서 객체 하나의 상태변화를 다른 연관 객체들에게 자동으로 통지하고 변경하고 싶을 때
- State (상태) : 객체의 내부 상태가 변경될 때, 해당 객체가 행동을 바꿀 수 있도록 하고 싶을 때
- Strategy (전략) : 실행 중에 알고리즘을 선택할 수 있게 하고 싶을 때
- Visitor (방문자) : 객체 구조를 이루는 요소들을 독립적으로 변경할 수 있도록 하고 싶을 때
- Template Method (템플릿 메서드) : 알고리즘의 골격을 변경하지 않고 알고리즘의 특정 단계를 재정의 하고 싶을 때