본문 바로가기
architecture

[My cheat-sheet] Design Patterns

by kanlee2010 2021. 7. 3.

디자인 패턴의 주요 관점:

1) 동일 코드 및 유사 코드까지 통합하려고 객체 지향의 다형성을 이용하여 코드 중복을 제거 하고

2) 객체 지향의 추상화 인터페이스 레벨을 맞추어 기존 코드를 수정하지 않고 새로운 코드를 추가하여 사용하도록 구성하는 방법 <-- 디자인 패턴의 첫번째 목적은 유지보수성(변경용이성), 두번째는 재사용(기존 패턴 방식의)

: 모양과 구성 방법이 같더라도 사용 목적에 따라 다르게 취급함. 예) Proxy pattern <-> Decorator Pattern

  생성 구조 행동
class 상속 Factory Method Adapter Interpreter
Template Method
객체 동적 변경 Abstract Factory
Builder
Prototype
Singleton
Adapter
Bridge
Composite
Decorator
Facade
Flyweight
Proxy
Chain of Responsibility
Command
Iterator
Madiator
Memento
Observer
State
Strategy
Visitor

각 디자인 패턴 설명

디자인 패턴   설명  다이어그램
Iterator 자료 저장과 자료 순회 역할을 독립적으로 분리하여 동일한 인터페이스로 접근하여 순차 접근할 수 있도록 구성,
오른쪽 그림에서 MyArray와 MyList는 자료 저장 역할을 하고 있으며 Position이라는 통일된 인터페이스로 자료 순회 역할을 분리하여 상세 구현한다. (← 단일 책임 원칙)

Composite 관련된 객체들을 하나의 인터페이스로 다룰 수 있도록 일관성을 부여 (예: 파일과 디렉토리를 같은 인터페이스로 접근 가능)
- 객체 컬랙션은 다시 다형성으로 상속하여 구현 할 수 있음: https://syseng.tistory.com/212
Command
execute(), undo(), redo() 등의 명령을 처리하는 일관된 인터페이스를 상속하는 객체로 구현 
Command + Composite 명령들의 묶음을 Composite 패턴을 활용하여 동일한 인터페이스로 처리: 오른쪽 MicroCommand class는 여러 명령들의 묶음을 가지는 Collection 객체 class
Proxy 다른 용도의 기능을 중간에 넣고 빼기 쉽게 하기 위해서 기존과 동일한 인터페이스를 상속하여 제공하고 기존 기능을 사용하기 위해서 다시 이 인터페이스를 통해서 기존 기능들로 재 구성(Composite 패턴과 유사) 할 수 있다. 오른쪽 그림 MySynchrozedList는 MyList 인터페이스를 통해서 기존 MyLinkedList class를 호출 함.
Decorator
상속없이 객체에 새로운 서비스를 추가하려는 목적,
Composite 패턴으로 다형성을 구현하여 중간 삽입/삭제가 용이하도록 함, Decorator끼리 겹쳐서 여러 기능을 사용 가능
Proxy와 Decorator는 생김새가 동일한데 사용하는 목적이 다름
Adapter 인터페이스가 다를 때 이를 일관된 인터페이스로 다시 제공하기 위해 해당 class를 일관된 인터페이스의 구현으로 감싸서 변환
Observer
객체들간 의존성을 최소화 하면서 여러 객체에 이벤트 전달, 구독자는 동적 증가/감소 가능, 상태가 변경되면 다른 객체들한테 연락 (상위 레이어로 callback 또는 listener에 사용: 역방향)
우측 그림에서 MyTextView(Observer)는 MyIntDocument(Subject)에 정보가 갱신되면 연락을 받는다. MyIntDocument::addObserver(MyTextView)
하면 내부적으로 MyView::update(Observable)가 호출됨.
https://syseng.tistory.com/213
(1:N) Pub/Sub 패턴과 유사한 듯 하지만 차이점 : Observer는 Broker가 없음.
Broker로 인해 Pub/Sub에서는 양쪽 모두 의존성이 없음.
Observer는 동기, Pub/Sub은 비동기
Mediator 관련된 객체 사이의 복잡한 제어를 Mediator에 집중
1) 초기화: Dialog는 ListBox, Button을 생성 후 Widget::setMediator(this)로 자신을 Mediator로 Widget에 등록함
2) 이벤트 호출: ListBox::widgetChanged() Widget::widgetChanged() → FileOpenDialog::childChanged() 로 호출됨
Observer는 Subject에서 trigger하지만 Mediator는 각 Colleague가 trigger 함
Visitor 데이터에 대한 멤버변수와 메소드를 분리하여 유지 보수 용이하게, 메소드를 별도의 Visitor 클래스로 분리하여 기능이 필요한 객체는 해당 Visitor 객체를 받아 드려서 수행.
우측 그림에서 Line::accept(VisitorSum) -> VisitorSum::visit(Line(this)) -> Line에서 정보 얻어서 VisitorSum 동작 수행, VisitorSum::visit()의 구현을 바꾸면 원하는 동작을 수정 가능
[문제점] Client에 각 구현 class 의존성 있음
Strategy 여러 상황에 따라 구현이나 알고리즘을 변경하여 사용할 수 있도록 (동적 변경도 가능)
우측 그림에서 Context는 각 Strategy들을 교체하여 사용, Client에서 AlgorithmA/B에 대한 의존성을 Context로 이동

Template Method 전체 구성은 같으나 몇몇 세부 동작이 다를 때
변경되는 단위스텝들을 abstract method로 선언 하여 상속된 객체에서 각각 다르게 구현
State 상태를 기반으로 한 행동을 캡슐화한 다음 위임을 통해서 필요한 행동을 선택,
switch/case 없이 구현, 상태 단위로 유지/보수가 이루어지기 때문에 상태 단위로 구현하는 것이 가독성과 유지/보수성이 좋다
: class 구성은 Strategy Pattern과 동일하나 캡슐화하는 내용과 목적이 다름
Bridge 기능과 상세 구현의 분리
기능 - Printer::drawLine()
상세 구현 - PrinterDev::PrintCmd1(), PrinterDev::PrintCmd2()
LajerPrinterDev가 추가될 경우 변경 사항은 LajerPrinterDev 추가와 의존성 주입만 수정
Chain of
Responsibility
(책임 연쇄)
Chain 객체들을 대상으로 연쇄적으로 요청을 전달하여 처리
요청을 하는 쪽과 받는 쪽의 의존성이 낮다
요청을 받는 객체가 자유롭게 추가/제거 가능
Chain의 각 객체들은 RequestHandler::handleRequest()를 구현 Chain의 각 객체들은 RequestHandler 인터페이스의 객체로 요청 전달 
Flyweight 중복되는 객체를 공유하면서 메모리 사용량을 줄이기 위해 객체의 상태들을 Client에서 관리하고 중복되는 객체는 형태로만 유지  
Facade 서브시스템에 대한 통합된 단순화된 인터페이스 제공  
생 성
Factory Method Factory 인터페이스를 상속한 구현 클래스에서 필요한 객체 생성, 오른쪽 그림에서 ProductImplement에 대한 의존성을 Client에서 FactoryImplement로 이동
Abstract Factory 여러 객체를 의존적으로 다르게 생성하고자 할때
우측 그림에서 Client는 WinWidgetFactory와 MacWidgetFactory만 알고 있고 각 Botton과 TextBox는 WidgetFactory가 알아서 생성함
Botton과 TextBox 생성 의존성을 WidgetFactory를 상속하는 객체로 이동
Builder 여러 단계와 다양한 절차를 통해서 객체를 생성 (Factory는 한 단계에서만 생성), 반면 Client는 객체 생성에 대한 정보를 더 많이 알아야 함.
우측그림에서 CsvBuilder와 HtmlBuilder는 MyBuilder 인터페이스를 상속하여 구현했으므로 buildTable()에서 MyBuilder 인터페이스를 이용하여 동작 함.
여러 ConcreteBuilder 중에 하나를 사용하는 것은 Strategy pattern과 유사한 구조로 볼 수 있음.
Prototype class name을 명시하지 않고 일관된 인터페이스로 객체를 새롭게 생성할 수 있는가? 생성 시  객체 복사 (deep copy) 필요
Singleton multi thread에 안전한 단일 인스턴스 생성  
Memento 객체의 중요한 상태를 따로 저장하는 역할의 Memento 객체로 이전 상태 복원  

모양이 유사한 디자인 패턴들

디자인 패턴 이름 다이어그램 차이점
Proxy
Adapter
  Proxy: 중간에 추가 되거나 수정 되는 기능들을 동일 인터페이스에서 대응하기 위해
Adapter:
가져온 라이브러리 인터페이스가 제공 해야 할 인터페이스와 서로 다를 때
Composite
Proxy
Decorator
Composite: 여러 객체 및 객체 컬랙션을 단일 인터페이스로 관리하기 위해
Proxy: 중간에 추가 되거나 수정 되는 기능들을 동일 인터페이스에서 대응하기 위해
Decorator: 상속없이 객체에 새로운 기능들을 추가하기 위해
Adapter
Facade
Bridge
Adapter: 서로 다른 인터페이스를 동일하게 맞춤
Facade: 복잡한 내부 내용을 단순한 인터페이스로 제공
Bridge: 기능 정의와 실제 상세 구현을 분리 하기 위해
Observer
Mediator
다이어그램은 서로 다름
개념이 상반됨
Observer: 단일 지점의 변경 내용을 여러 Subscriber들에게 연락
Mediator: 여러 하위 모듈들의 변경 내용을 Mediator로 모아서 처리 후 하위 모듈로 재 분배
Strategy
Template Method
구현하는 방식이 메소드 호출과 상속으로 차이  여러 상황에 따라 구현이나 알고리즘을 변경
Strategy: 동일 인터페이스에 다른 동작 구현
Template Method:
다른 동작 구현을 상속을 통하여 다형적으로 구현
Strategy
State
Builder
  Strategy: 동일 인터페이스에 다른 동작 구현을 캡슐화
State: 상태에 따른 행동을 캡슐화
Builder: 객체를 생성하는 해동을 캡슐화

참고한 블로그:

https://wellsw.tistory.com/category/%EC%8B%9C%EC%8A%A4%ED%85%9C%20%EC%84%A4%EA%B3%84%20%EB%B0%8F%20%EB%94%94%EC%9E%90%EC%9D%B8/%EB%94%94%EC%9E%90%EC%9D%B8%20%ED%8C%A8%ED%84%B4

 

'시스템 설계 및 디자인/디자인 패턴' 카테고리의 글 목록

 

wellsw.tistory.com

https://sncap.tistory.com/1093

 

디자인패턴

Design Pattern 디자인패턴은 앞서 설명한 바와 같이 목적에 따라 '생성', '구조', '행위' 패턴으로 나눌 수 있고, 범위에 따라 클래스를 대상으로 하느냐, 객체를 대상으로 하느냐, 로 나눌 수 있다. 1.

sncap.tistory.com

https://johngrib.github.io/wiki/pattern/

 

패턴

디자인 패턴, 아키텍처 패턴 등

johngrib.github.io

https://gmlwjd9405.github.io/tags#%EB%94%94%EC%9E%90%EC%9D%B8%ED%8C%A8%ED%84%B4

 

Tags - Heee's Development Blog

Step by step goes a long way.

gmlwjd9405.github.io

https://lktprogrammer.tistory.com/category/Study/%EB%94%94%EC%9E%90%EC%9D%B8%20%ED%8C%A8%ED%84%B4

 

'Study/디자인 패턴' 카테고리의 글 목록

IT / 프로그래밍 관련 강의 자료를 공유하고 딱딱한 일상에서 벗어나 여행/맛집 일상을 공유하는 블로그입니다 ^^

lktprogrammer.tistory.com

 

'architecture' 카테고리의 다른 글

observer design pattern example  (0) 2022.11.29
composite design pattern example  (0) 2022.11.29
[My cheat-sheet] PUML  (0) 2021.09.29

댓글