디자인 패턴 찍어 먹어 보기

eden6187·2021년 8월 15일
0

OOP

목록 보기
1/1
post-thumbnail

Creational Patterns

Factory Method

  • 해결하고자 하는 문제 :
    • 객체 생성을 확장성 있게 가져가고 싶다.
  • 어떻게 :
    • 템플릿 메소드의 생성 버전이라고 생각하면 된다.
    • 상위 클래스는 인스턴스를 생성하는 메소드에 대한 정의만 해놓는다. (구체적인 객체 생성 작업은 하위 클래스에 위임한다.)
    • 하위 클래스가 인스턴스를 생성하는 메소드를 직접 구현한다.
  • 장점 :
    • 객체의 생성을 담당하는 메소드를 분리 할 수 있다.
    • 새로운 타입을 쉽게 도입 할 수 있다.
  • 단점 :
    • 새로운 하위 클래스를 많이 도입하다 보면 코드가 복잡해 질 수 있다.
  • 관련 SOLID :
    • SRP
    • OCP

Abstract Factory

  • 해결하고자 하는 문제 :
    • 자주 같이 사용되는 객체들을 한 곳에서 만들어주고 싶다.
    • Factory Method의 연장선이라고 생각하며 된다. 다만, 같이 사용되는 객체들을 하나의 Factory에서 생성 할 수 있다.
  • 어떻게 :
    • Abstract Factory 클래스가 여러개의 Factory Method를 정의하고 있는다.
    • Concrete Factory 클래스에서 이를 구현한다.
  • 장점 :
    • 같은 Factory에서 사용되는 Product들이 다른 Product들과 호환성이 있다는 것을 보장 할 수 있다.
  • 단점 :
    • Factory를 구현하는 구체 클래스가 많아지면 코드가 복잡해 질 수 있다.
  • 관련 SOLID : -

Builder

  • 해결하고자 하는 문제 : 객체를 생성하고자 할 때 필요한 요소들이 너무 많거나, 일부는 사용하지 않음
  • 어떻게 : 차근차근 필요한 것들만 넣어가면서 객체를 생성
  • 장점 :
    • 객체를 단계별로 생성 가능
    • 같은 코드를 이용해서 다양한 인스턴스 생성 가능
  • 단점 : -
  • 관련 SOLID:
    • SRP

Singleton

  • 해결하고자 하는 문제:

    • 특정 class의 인스턴스가 유일했으면 좋겠다.
    • instance에 대한 전역적인 접근(global access) 을 가능하게 한다.
  • 어떻게 :

    • 생성자를 private으로 만들고
    • static 한 creation method를 만든다.
  • 장점 :

    • global access point 생성 가능
    • 인스턴스의 유일성 보장 가능
  • 단점 :

    • Singleton 객체에 데이터를 공유하다 보면 객체들이 서로에 대해서 너무 많이 알게 된다.
    • 멀티스레드에서 구현 이슈가 있다.
      • 생성하는 과정이 여러 단계로 나누어져 있을 경우 멀티 스레드 상황에서 1개 이상의 인스턴스가 만들어 질 수 있다.
      • 결론 : 대부분의 상항에서는 원소가 하나뿐인 열거 타입이 싱글턴을 만드는 가장 좋은 방법이다.(effective java - item3)
    • 생성자가 private으로 막혀있기 때문에 상속이 안된다.
    • Java에서 직렬화 이슈가 있다.
    • 상속을 사용하는 Framework에서 테스트 하기가 아주 드릅다...
  • 관련 SOLID :

    • SRP 위배

Prototype

  • 해결하고자 하는 문제:
    • 새로운 것을 생성하는데 많은 자원이 필요한 객체의 경우 기존의 객체를 복사하고 필요한 부분만 수정해서 사용하고 싶다.
  • 어떻게 :
    • 구상체가 Prototype의 인터페이스를 구현(clone() 메소드 포함)한다.
  • 장점 :
  • 단점 :
    • 참조가 복잡한 객체를 복사할경우 순환참조가 발생할 수 있다.
  • 관련 SOLID : -

Structural Patterns

Adapter

  • 해결 하고자 하는 문제 : 서로 다른 interface를 가진 객체들끼리의 호환을 가능하게 하고 싶음.
  • 어떻게 :
    • Adapter가 하나의 Interface를 구현하고, 또 다른 Object에 의존한다.(wrap한다.)
  • 장점 :
    • 비즈니스 로직에서 interface와 data 변환 분리 가능
    • 기존코드를 수정하지 않으면서, 새로운 Adapter를 만들 수 있다.
  • 단점 :
    • Interface, Class가 많아지다 보면, 코드의 복잡도가 상승한다.
  • 관련 SOLID:
    • SPR
    • OCP

Bridge

  • 해결하고자 하는 문제 :

    • 기능 계층구현 계층의 분리 ( extends와 Implementation의 차이를 생각 )

    • 구현 계층 :

      ⇢ 껍데기는 그대로 두고, 내용물만 바꾼다는 느낌??

    • 기능 계층 :

      ⇢ 실제로 새로운 기능을 추가하여 클래스를 좀 더 특수하게 만드는 것??

  • 어떻게 :

    • 구현 계층이 기능 계층을 Member로 가지도록 한다. (Composition)
  • 장점 :

    • platform에 종속적이지 않은 class를 만들 수 있다.
  • 단점 :

    • 코드 복잡성 증가
  • 관련 SOLID :

    • OCP
    • SRP

Composite

  • 해결하고자 하는 문제 : 담을 것과 담길 것에 같은 Operation을 취하고 싶다. ( 파일과 디렉토리는 서로 다르지만, 둘다 "용량 구하기" 같은 operation을 취할 수 있다.)

  • 어떻게 :

    • 담을 물건(Leaf)과 물건을 담을 곳(Composite)를 추상화 한다.(Component)
  • 장점 :

    • 다형성과 재귀를 이용하여 tree-structure를 간편하게 관리 할 수 있다.
    • 기존 코드를 수정하지 않고 tree 구조 사용 가능
  • 단점 :

    • 성질이 많이 다른 Object들을 추상화하여 tree 의 Component로 만드는 것이 지나친 추상화가 될 수 있다.
  • 관련 SOLID :

    • OCP

Decorator

  • 해결하고자 하는 문제 : 객체에 필요에 따라 기능을 추가하고 싶은 경우에 사용.
  • 어떻게 :
  • 장점 :
    • 상속없이 객체를 구체화 시킬 수 있음.
    • 런타임에 객체의 책임을 결정 할 수 있음.
  • 단점 :
    • Decorating(즉, wrapper를 달기는 쉽지만, 제거는 어렵다.)
    • Decorate되는 순서에 종속적이지 않도록 Decorator를 설계하는 것이 어렵다.
    • Decorator를 달아서 생성하는 코드가 너저분하다. New..new...new..new..
  • 관련 SOLID:
    • SRP

Facade

  • 해결하고자 하는 문제 : 복잡한 과정을 추상화 해서 간단한 인터페이스로 제공하고 싶다.
  • 어떻게 :
    • 복잡한 일련의 과정들을 하나의 메소드 혹은 클래스에 묶는다.
  • 장점 :
    • 복잡한 subsystem을 추상화 해서 사용 할 수 있다.
  • 단점 :
    • facade가 너무 거대해지면 너무 많은 역할을 동시에 수행하게 된다. ( God Object가 된다. )
  • 관련 SOLID : -

Flyweight

  • 해결하고자 하는 문제 : 공통적인 부분들에 대한 중복 때문에 memory 효율이 좋지 못할 경우, 공통되는 부분들은 1개만 만들어서 공유 하도록 하자! (즉, 최적화를 위한 패턴임!)

  • 어떻게 :

    • Extrinsic State : 각 인스턴스마다 고유한 값

    • Intrinsic State : 변하지 않는 공통적인 필드

    • Intrinsic State를 분리하되, Immutable하게 분리한다.

    • 팩토리 클래스를 정의해서 새로운 인스턴스를 생성하고자 할 때, Extrinsic한 값들은 인스턴스별로 고유하게 가지도록 하고, Intrinsic한 값들은 기존에 존재하는 값을 사용하도록 즉, 공유 할 수 있도록 한다.

  • 장점 :

    • 적절하게 사용한다면, 메모리를 적게 사용할 수 있다.
  • 단점 :

    • 코드의 복잡성이 증가한다.
    • 메모리를 적게 사용하지만, CPU는 많이 사용하게 될 수 도 있다.
  • 관련 SOLID : -

Proxy

  • 해결 하고자 하는 문제 :

    • Client가 Server가 Real인지 Proxy인지 모르게 하고 싶다.
  • 어떻게 :

    • 추상화 된 인터페이스 정의
    • Client는 인터페이스에 의존하기 때문에 현재 참조하는 객체가 Proxy인지 Real인지 알 수 없음.
    • Client가 Proxy에게 Real 객체가 필요한 특정한 Method를 호출하게 되면 Proxy는 그때서야 Real 객체에게 Operation을 가한다.
    • Client는 지속해서 Proxy를 통해서 Real을 사용.
  • 장점 :

    • Client에게 Server의 정보를 숨길 수 있다.
    • Real Server가 실제로 존재하지 않아도 Proxy를 통해서 있는 것 처럼 보여 줄 수 있다.
  • 단점 : -

  • 관련 SOLID : -

Behavioral Patterns

Chain of Responsibility

  • 해결 하고자 하는 문제 :

    • 처리 과정을 유연하게 가져가고 싶다. (처리 순서를 동적으로 변경 할 수 있다.)
  • 어떻게 :

    • Handler가 처리 할 수 있는 Request를 정의한다.

    • Handeler에 setNext(), handle(request)를 정의한다.

  • 장점 :

    • request의 처리 순서를 유연하게 가져 갈 수 있다.
  • 단점 :

    • request가 제대로 처리 되지 않을 수 있다.
  • 관련 SOLID :

    • SRP
    • OCP

Command

  • 해결 하고자 하는 문제 :
    • operation의 호출(Input에 따라서 구체적인 operation을 생성만 하고)과 operation의 수행을 분리(operation의 종류와 관계없이 해당 operation의 처리만 담당.)
  • 어떻게 :
    • Command Interface 정의
    • Command Interface를 구현하는 구체적인 Class들을 구현
    • Command를 실행하는 Client는 Command의 구체적인 Type과 관계없이
    • Command를 실행만 하면 된다.
  • 장점 :
    • operation을 호출(invoke)하는 객체와 operation을 수행하는 객체를 나눌 수 있음.
    • 새로운 operation을 도입하기 쉬움
    • undo/redo를 구현 할 수 있음
    • operation의 버퍼링 가능
    • 간단한 여러가지 Command를 조합하여 어려운 Command를 만들 수 있음
  • 단점 :
    • 구조가 복잡해 질 수 있다.
  • 관련 SOLID :
    • SRP
    • OCP

Iterator

  • 해결 하고자 하는 문제 :
    • Collection의 종류와 상관 없이 Collection을 순회 할 수는 없을까?
  • 어떻게 :
    • 추상화된 Iterator, IterableCollection 정의
    • 각각을 구현
    • Client는 Iterator와 IterableCollection에 의존.
  • 장점 :
    • superclass에 중복된 코드를 몰아 놓을 수 있음.
    • client가 자유롭게
  • 단점 :
    • 특정 Collection에 대해서는 Iterator를 사용하는 것이 더 낭비 일 수 있다.
  • 관련 SOLID :
    • OCP
    • SRP

Mediator

  • 해결 하고자 하는 문제 :

    • 객체들간의 복잡한 dependncy를 줄이고 싶다.

      ⇢ 객체들 사이에 mediator를 두고 mediator를 통해서 간접적으로 상호작용하도록 한다.

  • 어떻게 :

    • Mediator 인터페이스 정의 ⇢ Mediator 구현체 정의
    • Component들이 Mediator의 특정 메소드를 통해서 다른 Component와 통신이 가능하다.
  • 장점 :

    • 다양한 Componenet들의 통신 로직을 분리 할 수 있다.
    • Mediator가 추상화 되어 있으면 새로운 구체 타입의 Mediator를 도입할 수 있다.
  • 단점 :

    • Mediator가 Go Object가 될 가능성이 있다.
  • 관련 SOLID :

    • OCP
    • SRP
  • Reference : -

Memento

  • 해결 하고자 하는 문제 :

    • 객체의 상태를 저장하고, 이전 상태로 복구

    • 인스턴스를 캡슐화 하면서, 인스턴스의 상태에 대한 저장과 복원을 할 수는 없을까

  • 어떻게 :

    • Originator : Memento를 생성하고, Memento를 이용해 상태 복구
    • Memento : Originator에 대한 상태를 가지고 있음. 단, Originator의 정보를 담고 있다. 이때, Memento에 담긴 정보를 Encapuslation을 잘 해주는 것이 Memento 패턴의 핵심이다.
    • Caretaker : Memento를 언제 생성하고, 언제 복구 할지를 결정
  • 장점 :

    • encapsulation을 지키면서, 객체에 대한 snanpshot을 생성 할 수 있다.
    • originator와 caretaker를 분리 하면서 originator을 단순화 할 수 있다.
  • 단점 :

    • Memento가 너무 많아지면 메모리 낭비가 심해진다. ⇢Caretakers가 Memento를 잘 관리하는 것이 포인트
    • Encapuslation 기능을 지원하지 않는 언어에서는 Encapusation을 제대로 할 수 없다.
  • 관련 SOLID : -

Observer

  • 해결 하고자 하는 문제 :
    • 객채의 상태 변화를 확인 하고 싶다.
  • 어떻게 :
    • Publisher와 Subscriber(Observer)를 정의
    • Subscriber를 Pulisher에 등록 또는 삭제
    • Publisher의 notifySubscribers()를 호출하게 되면
    • Publisher가 등록된 Subscriber객체들의 notify() 함수를 호출
  • 장점 :
    • OCP
  • 단점 :
    • Subscriber가 notify() 받는 순서를 보장 할 수 없다.
  • 관련 SOLID :
    • OCP

State

  • 해결 하고자 하는 문제 :

    • 유한한 상태가 있을 때(Ex. 5가지 상태중에서 왔다 갔다 함)
    • 상태에 따라서 객체의 행동을 바꾸어주고 싶은 경우
  • 어떻게 :

    • State에 따라서 동작이 달라지는 Context를 결정한다.

    • State Interface를 정의한다.

  • 장점 :

    • 조건문으로 도배된 코드를 단순화 할 수 있다.
    • 새로운 State를 기존 코드의 수정 없이 도입 할 수 있다.
  • 단점 :

    • 상태가 몇가지 없을 경우 과도한 작업 일 수 있다.
  • 관련 SOLID :

    • OCP

Strategy

  • 해결 하고자 하는 문제 :

    • 알고리즘에 대한 인터페이스만 제공하고, 알고리즘의 내용은 동적으로 바꾸고 싶다.
  • 어떻게 :

    • 추상화 된 인터페이스에 메소드를 정의
    • 해당 인터페이스의 메소드를 통해 알고리즘 호출
    • 알고리즘의 변경의 필요한 경우 구현체의 내부 로직만 바꾸면 된다.
  • 장점 :

    • 로직을 런타임에 변경 가능
    • Client가 Server의 내부 알고리즘 구현에 대해서 알 필요가 없음.
  • 단점 :

    • 알고리즘의 변화가 적은 경우 이 패턴을 적용하는 것이 코드 자체를 더 난잡하게 할 수 있다.
    • Functional Interface를 통해 대체가 가능하다.
  • 관련 SOLID :

    • OCP

Template Method

  • 해결 하고자 하는 문제 :

    • 큰 틀에서 수행 해야 할 일을 정해 놓고(template method), 세부적인 구현은 알아서 해라!
  • 어떻게 :

    • 추상화 된 클래스에 template method 정의
    • template method 내부 method들의 구현은 상속후 직접 구현
    • Client는 추상 클래스에 의존하면서 template method만을 호출
  • 장점 :

    • superclass에 중복된 코드를 몰아 놓을 수 있음.
    • client가 자유롭게 template method 내부의 method들을 커스텀 할 수 있다.
  • 단점 :

    • 하위 클래스를 통한 기본 단계 구현을 억제하여 Liskov 대체 원칙을 위반할 수 있다?

    • template method 내부 수행 절차가 변경되면, 유지 보수가 굉장히 까다롭다.

  • 관련 SOLID :

    • OCP

Visitor

  • 해결 하고자 하는 문제 :

    • 객체에서 처리를 분리해서 사용할 수 있다.
  • 어떻게 :

    • Visitor, Visitable 정의
    • Visitable은 Visit을 accept한 후에 Visit의 인스턴스를 통해 특정 메소드(visitOO()) 실행
  • 장점 :

    • 각기 다른 Class에 대해서 Class를 수정하지 않고 새로운 작업을 수행 할 수 있다.
    • 동일한 동작을 하나의 Class에 모아 놓을 수 있다.
  • 단점 :

    • Visitor가 Visitable의 Private Method에 접근 할 수 없을 수 있다.
    • Visitable의 Type이 늘어날때 마다 Visitor를 수정해주어야 한다.
  • 관련 SOLID :

    • SRP
    • OCP

Reference

0개의 댓글