/designPattern

GoF(gang of four) 디자인 패턴 java 코드로 구현해보기

Primary LanguageJava

designPattern

  • 특정 문맥에서 공통적으로 발생하는 문제에 대한 재사용 가능한 해결책
  • SW를 디자인할 때 공통적이고 반복된 문제들을 해결하는데 쓰이는 형식화된 좋은 관행!
  • 항상 적용할 필요는 없고 사례를 참고하는 게 좋다.
    • 모범사례를 통해 시야확장
    • 유연한 설계를 지닌 객체지향의 장점
    • 디자인 패턴의 이름으로된 클래스들이 이미 다수 존재한다.
      • 코드를 이해하기 위해 필요

GoF(gang of four) 디자인 패턴 구분

  • 생성패턴
    • 객체 생성 혹은 조합에 관한 패턴
  • 구조패턴
    • 객체를 조합해 더 큰 구조를 만드는 패턴
    • 새로운 기능을 추가하는데 관련된 패턴
  • 행위패턴
    • 객체 사이 책임분배나 커뮤니케이션에 관한 패턴
    • 단일 객체가 처리해야될 일을 여러 객체로 나눌 때 어떻게 배분하면서 결합도를 낮출지

Singleton (생성패턴)

  • 클래스의 인스턴스가 1개임을 보장하고 싶다.
  • 인스턴스 생성을 제어할수 있어야함.
  • 1개뿐인 인스턴스에 쉽게 접근할 수 있어야함(글로벌 객체)
  • 지연로딩 전략 가능

Builder (생성패턴)

  • 복잡한 객체의 생성방법과 표현방법을 분리해야 함.
  • 생성방법과 구성방법 모두 캡슐화 해야 함.
  • 객체 생성에 필요한 파라미터가 너무 많아 생성자 오버로딩이 과할 때 유용
  • 자바에선 named parameter 기능이 없어 lombok의 빌더패턴이 자주 쓰인다

Factory Method (생성 패턴)

  • 복잡한 객체 생성을 캡슐화 해야한다.

  • 생성은 다른 클래스에게 위임하려한다.

    • 빌더패턴도 실제 객체의 생성은 빌더에 위임했다.
  • 어떤 인스턴스를 만들어야 할지 알 수 없음.

    • 빌더의 경우 1:1 매핑이지만 팩토리는 여러가지를 만들 수 있다.

    Untitled

팩토리 구현 방식

  • 하나의 팩토리에서 타입을 받아 각각의 구현체를 얻는 방식
  • 팩토리 자체가 여러 개로 나뉘어 타입을 주지 않고도 원하는 구현체를 제공해주는 팩토리방식
    • 각각 장단이 있지만 스프링에서는 빈 DI를 사용하기 때문에 이 방식이 좀 더 유용할 수 있다.

Adaptor (구조 패턴)

  • 서로 다른 시스템, 인터페이스 등을 함께 동작(연결)하고자 할 때 ( 실제 어댑터의 역할 ) 기대하는 다른 인터페이스로 변환하는 패턴

해결할 수 있는 문제

  • 클라이언트에 필요한 인터페이스가 없는 클래스를 재사용할 수 있다.
  • 호환되지 않는 인터페이스가 있는 클래스를 작동시킬 수 있다.
  • 클래스에 대한 대체 인터페이스를 제공해줄 수 있다.

핵심 아이디어

  • adapter(이미 존재하는) 클래스의 인터페이스를 변경하지 않고 별도의 작업을 수행하는 것

Facade {건물의 전면 또는 외부를 의미하는 프랑스 용어에서 차용.} (구조 패턴)

  • 복잡한 서브시스템의 인터페이스를 단순하게 구성하고자 할 때
  • 시스템간 결합도를 줄이고자 할 때
  • 서브시스템을 계층화 시키고 싶을 때
  • 간단하게 정리하면, 복잡한 로직을 캡슐화하여 간단한 인터페이스로 제공해 줌으로써 객체를 사용하는 클라이언트 단에서는 뒤의 복잡한 로직을 알지 않아도 된다.

Decorator (구조 패턴)

  • 기존 객체를 수정 없이 새로운 책임을 추가하고 싶을 때
  • 객체를 사용하는 클라이언트에 코드의 변경 없이 책임을 추가할 수 있다.
  • 단일 책임 원칙 을 준수하는데 유용하다.

원래 클래스를 감싸는 새로운 Decorator 클래스를 설계함으로써 기존 클래스에 변경 없이 기능을 확장(장식,decorate)할 수 있다. 이 패턴은 재정의된 메서드에 새 기능을 추가할 때마다 여러 데코레이터를 서로 쌓을 수 있도록 설계되어서 유연한 확장이 가능하다.

Proxy (구조 패턴)

다른 항목에 대한 인터페이스 역할을 하는 클래스이다.

  • 객체에 접근을 제어하고 싶을 때 사용할 수 있다.
  1. 객체를 실제 사용하기 전까지 초기화를 미루고 싶을 때 ex) JPA ENTITY LAZY 로딩 시
  • 개체에 액세스할 때 추가 기능을 제공해야 합니다.
  1. 예를 들어 민감한 개체에 액세스할 때 클라이언트에 필요한 액세스 권한이 있는지 확인할 수 있어야 한다.

데코레이터 패턴과 유사하지만 데코레이터 패턴은 새 기능을 추가하는데 초점이 있고 프록시 패턴은 객체의 액세스 제어에 초점이 있다.

Strategy (행동 패턴)

실행 중에 알고리즘을 선택할 수 있게 하는 행위 소프트웨어 디자인 패턴이다.

  • 클라이언트의 코드 변경 없이 독립적으로 문제 해결 전략을 바꾸고 싶을 때
  • 다양한 문제해결 방법을 제공해야 할 때
  • 특정한 계열의 알고리즘들을 정의하고 각 알고리즘을 캡슐화하여 이 알고리즘들을 해당 계열 안에서 상호 교체가 가능하게 만든다.

Template method (행동 패턴)

기능의 뼈대(템플릿)과 실제 구현을 분리하는 패턴이다.

  • 구체적인 처리방법은 하위 클래스로 위임하고자 할 때

전략패턴과의 비교

  • 전략패턴이 구체적인 구현내용을 숨기고 쉽게 교체할 수 있게 만드는데 목적이 있다면
  • 템플릿 메서드 패턴은 기능(이미 기술된 상위로직)에서 특정 로직, 단계만 제어하고 싶을 때 사용한다.

단점

  • template 메서드 자체가 변경될 여지가 있으면 사용하면 안된다. 그렇기에 전략패턴과의 차이를 명확히 이해하고 사용해야 한다.
  • 예를들어 전략패턴으로 구현을 했는데 중복되는 로직이 있어서 템플릿메서드 패턴으로 바꿨지만 알고보니 그쪽만의 flow 였고 다른 쪽을 사용할 때 다른 flow로 돌아갈 수 있다.
  • 결론은 템플릿에 예외 케이스가 생길 수 있다면 사용하지 않는 것이 좋다.

Chain of Responsibility (행동 패턴)

  • 메시지를 보내는 객체와 처리하는 객체를 분리하고 싶을 때

  • 하나의 메시지를 여러 객체가 처리해야할 때

  • 자료구조의 링크드리스트와 유사하다.

  • 코드 수정 없이 handler 확장이 가능 (OCP)

  • 명령을 내리는 객체와 수행하는 객체의 분리 (SRP)

  • 자바의 try-catch 구문이 책임연쇄패턴으로 작성되어있다.

  • 각 catch 구문들은 자기가 처리하거나, 다음 catch 구문으로 책임을 넘긴다.