지식

11개 디자인패턴 자세히 알아보기

colin2 2025. 7. 9. 18:25
Strategy (전략) 패턴

[상황] 과일 매장에서 상황에 따라 다른 가격 할인 정책을 적용할 때, 가격을 계산하는 모듈에 가격 할인 정책을 적용하기 위해 if-else 블록을 추가하게 됨

 

[문제] 서로 다른 계산 정책들이 한 코드에 섞여 있어, 정책이 추가될수록 코드 분석을 어렵게 함

 

가격 할인 알고리즘(계산 방법)을 추상화한 것을 Strategy(전략), 가격 계산 기능 자체의 책임을 갖고 있는 것을 Context(콘텍스트)라고 부르는데, 이렇게 특정 콘텍스트에서 알고리즘(전략)을 별도로 분리하는 설계 방법이 전략 패턴

전략 객체는 콘텍스트를 사용하는 클라이언트에서 직접 생성

 

[장점] 콘텍스트 코드의 변경 없이 새로운 전략을 추가할 수 있음, 할인 정책 확장에는 열려 있고 변경에는 닫혀 있으므로 개방 폐쇄 원칙을 따르눈 구조를 갖게 됨

 

일반적으로 if-else로 구성된 코드 블록이 비슷한 기능(비슷한 알고리즘)을 수행하는 경우에 전략 패턴을 적용함으로써 코드를 확장 가능하도록 변경할 수 있음

완전히 동일한 기능을 제공하지만 성능의 장단점에 따라 알고리즘을 선택해야 하는 경우에도 전략 패턴 사용

 

Template Method (템플릿 메서드) 패턴

[상황] 실행 과정/단계는 동일한데 각 단계 중 일부의 구현이 다른 경우에 사용

 

[구성]

상위 클래스 : 실행 과정을 구현한 메서드 제공, 이 메서드는 기능을 구현하는데 필요한 각 단계를 정의하며 이 중 일부 단계는 추상 메서드를 호출하는 방식으로 구현, 이때 추상 메서드는 구현이 다른 단계에 해당

하위 클래스 : 실행 과정의 일부 단계를 구현, 상속받은 하위 클래스는 다른 메서드만 알맞게 재정의하면 됨

 

[특징] 하위 클래스가 아닌 상위 클래스에서 흐름 제어를 함, 상위 타입의 템플릿 메서드가 모든 실행 흐름을 제어하고, 하위 타입의 메서드는 템플릿 메서드에서 호출되는 구조, 하위 타입에서 재정의 해야 하는 메서드는 private이 아닌 protected의 범위를 가져야 함

 

State (상태) 패턴

[상황] 기능이 상태에 따라 다르게 동작해야 할 때 사용

 

[특징] 상태 객체가 기능을 제공

 

[장점] 새로운 상태가 추가되더라도 콘텍스트 코드가 받는 영향은 최소화 됨

상태에 따른 동작을 구현한 코드가 각 상태 별로 구분되기 때문에 상태 별 동작을 수정하기 쉬움

 

Decorator (데코레이터) 패턴

[상황] 상속을 이용한 기능 확장 방법이 쉽긴 하지만, 다양한 조합의 기능 확장이 요구될 때 클래스가 불필요하게 증가하는 문제가 발생, 이런 경우에 사용할 수 있는 패턴이 데코레이터 패턴

데코레이터 패턴은 상속이 아닌 위임을 하는 방식으로 기능을 확장

 

[장점] 데코레이터를 조합하는 방식으로 기능을 확장할 수 있음, 데코레이터의 생성 순서를 변경해 주기만 하면 기능 적용 순서도 쉽게 변경 가능

각 확장 기능들의 구현이 별도의 클래스로 분리되기 때문에, 각 확장 기능 및 원래 기능을 서로 영향 없이 변경할 수 있도록 만들어 줌, 즉, 단일 책임 원칙을 지킬 수 있게 만들어 줌

 

Proxy (프록시) 패턴

[상황] 제품 목록을 구성할 때 관련된 모든 이미지를 로딩하도록 구현할 경우, 불필요하게 메모리를 사용하는 문제 발생, 이런 상황에서 이미지 로딩 방식을 교체할 수 있도록 해 주는 패턴이 프록시 패턴, 프록시 패턴은 실제 객체를 대신하는 프록시 객체를 사용해서 실제 객체의 생성이나 접근 등을 제어할 수 있도록 해 주는 패턴

 

proxy 객체의 메서드가 호출되기 전에는 이미지 데이터를 로딩하지 않으므로 불필요하게 메모리를 낭비하는 상황을 방지할 수 있음

 

Adapter (어댑터) 패턴

[상황] 웹 게시판 게시글의 개수가 빠르게 증가하면서 SQL의 like를 이용한 검색 속도 성능에 문제가 발생하여 Tolr라는 오픈 소스 검색 서버를 도입하려 했으나, 기존 인터페이스와 Tolr가 제공하는 인터페이스가 맞지 않을 때 사용할 수 있는 패턴이 어댑터 패턴

 

적용하려는 인터페이스를 기존 인터페이스에 맞춰 주는 책임을 가짐

 
Observer (옵저버) 패턴

[상황] 한 객체의 상태 변화를 정해지지 않은 여러 다른 객체에 통지하고 싶을 때 사용되는 패턴

 

[구조] 주제(subject) 객체와 옵저버(observer) 객체

  • 주제 객체의 책임
    • 옵저버 목록을 관리하고, 옵저버를 등록하고 제거할 수 있는 메서드 제공
    • 상태의 변경이 발생하면 등록된 옵저버에 변경 내역을 알림

 

[장점] 주제 클래스 변경 없이 상태 변경을 통지 받을 옵저버를 추가할 수 있음

 

Mediator (미디에이터) 패턴

[상황] 여러 기능을 가진 비디오 플레이어를 만들었을 때, 비디오가 아닌 MP3에 적용하려 할 때, 필요한 코드만 추려 내야 하고, 함께 사용되는 클래스가 증가할수록 개별 클래스의 수정이 어려워짐, 미디에이터 패턴은 각 객체들이 직접 메시지를 주고받는 대신, 중간에 중계 역할을 수행하는 미디에이터 객체를 두고 미디에이터를 통해서 각 객체들이 간접적으로 메시지를 주고받으니 이 패턴을 사용하면 됨

 

Facade (파사드) 패턴

[상황] 직원 정보, 직원의 이력 정보, 직원에 대한 평가 정보를 읽어 화면에 보여주는 GUI 프로그램을 만들었는데, HR팀으로부터 화면뿐만 아니라 XML이나 액셀로 동일한 데이터를 추출해 달라는 요구 사항이 들어오면, 각각에서 코드 중복이 발생함, 코드 중복과 직접적인 의존을 해결하는데 도움을 주는 패턴이 파사드 패턴, 파사드 패턴은 서브 시스템을 감춰 주는 상위 수준의 인터페이스를 제공함으로써 이 문제를 해결함

 

[장점] 클리아언트 코드가 간결해지고, 클라이언트와 서브 시스템 간의 직접적인 의존을 제거

파사드를 인터페이스로 정의함으로써 클라이언트의 변경 없이 서브 시스템 자체를 변경할 수 있음

 

Abstract Factory (추상 팩토리) 패턴

[상황] 비행기를 조종하고 미사일을 발사해서 적을 미사일로 쏴 맞추는 슈팅 게임을 만들 때, 각 Stage 클래스는 몇 단계인지에 따라 서로 다른 적기, 장애물 또는 보스를 생성해야 함, Stage 클래스로부터 객체 생성 책임을 분리함으로써 이 문제를 해소할 수 있는 것이 추상 팩토리 패턴

 

관련된 객체 군을 생성하는 책임을 갖는 타입을 별도로 분리

 

[장점] 클라이언트에 영향을 주지 않으면서 사용할 제품(객체)군을 교체할 수 있음

 

Composite (컴포지트) 패턴

[상황] 빌딩의 장비들의 전원을 관리하는 제어 프로그램을 개발할 때, 개별 장비와 그룹 장비들을 관리할 클래스를 추가하여 거의 동일한 메서드가 중복이 됨, 이때 사용되는 패턴이 컴포지트 패턴

 

  • 컴포지트 패턴에서 컴포지트의 책임
    • 컴포넌트 그룹 관리
    • 컴포지트에 기능 실행을 요청하면, 컴포지트는 포함하고 있는 컴포넌트들에게 기능 실행 요청을 위임

 

[장점] 전체냐 부분이냐에 상관 없이 클라이언트는 단일 인터페이스로 기능을 수행할 수 있음

컴포지트 자체도 컴포넌트이기 때문에, 컴포지트에 다른 컴포지트를 등록할 수 있음