실전에서의 디자인 패턴

Head First - Design Patterns
(에릭 프리먼, 엘리자베스 프리먼, 케이시 시에라, 버트 베이츠 저 | 서환수 역)
을 읽고 정리한 내용입니다.


디자인 패턴 정리

  1. 데코레이터 패턴
    : 객체를 감싸서 새로운 행동을 제공한다.
  2. 스테이트 패턴
    : 상태를 기반으로 한 행동을 캡슐화한 다음 위임을 통해서 필요한 행동을 선택한다.
  3. 이터레이터 패턴
    : 컬렉션이 어떤 식으로 구현되었는지 드러내진 않으면서도 컬렉션 내에 있는 모든 객체에 대한 반복 작업을 처리할 수 있게 해준다.
  4. 퍼사드 패턴
    : 일련의 클래스에 대해서 간단한 인터페이스를 제공한다.
  5. 스트래티지 패턴
    : 교환 가능한 행동을 캡슐화하고 위임을 통해서 어떤 행동을 사용할지 결정한다.
  6. 프록시 패턴
    : 객체를 감싸서 그 객체에 대한 접근을 제어한다.
  7. 팩토리 메서드 패턴
    : 생성할 구상 클래스를 서브클래스에서 결정한다.
  8. 어댑터 패턴
    : 객체를 감싸서 다른 인터페이스를 제공한다.
  9. 옵저버 패턴
    : 상태가 변경되면 다른 객체들한테 연락을 돌릴 수 있게 해준다.
  10. 템플릿 메서드 패턴
    : 알고리즘의 개별 단계를 구현하는 방법을 서브클래스에서 결정한다.
  11. 컴포지트 패턴
    : 클라이언트에서 객체 컬렉션과 개별 객체를 똑같이 다룰 수 있도록 해 준다.
  12. 싱글턴 패턴
    : 딱 한 객체만 생성되도록 한다.
  13. 추상 팩토리 패턴
    : 클라이언트에서 구상 클래스를 지정하지 않으면서도 객체 그룹을 생성할 수 있도록 해 준다.
  14. 커맨드 패턴
    : 요청을 객체로 감싼다.

디자인 패턴 분류하기

디자인 패턴의 분류를 공부하고 외우는 건 우선 순위가 높은 지식은 아니므로
가볍게 보도록 하자.

  1. 생성, 행동, 구조 관련 패턴으로 나누는 경우
  2. 클래스와 객체 패턴으로 나누는 경우

리팩토링(refactoring)

리팩토링을 할 경우, 인터페이스가 변경되면 안 된다.
클라이언트 코드를 변경해야 한다면, 리팩토링이라고 할 수 없다.

public method를 변경해서 return 타입이 바뀔 경우는
엄밀히 따지자면 리팩토링이라고 보기 어렵다.
클라이언트에서 코드를 변경해야 하므로 스펙 변경이라고 볼 수 있다.

그럼 리팩토링이란 무엇일까?

리팩토링은 코드를 변경하되 외부에는 변경을 노출하지 않는 것이다.

private method의 경우에는 return type이 바뀌는 것도 리팩토링이라고 할 수 있다.
(코드 변경의 여파가 클라이언트까지 미치지 않기 때문이다. )

패턴을 대하는 마음가짐

초보자들은 언제나 패턴을 사용하는 경향이 있다.
어떻게 패턴을 사용하면 좋을지 고민하는 성장의 과정이라고 볼 수 있다.

패턴을 쓰면 안 될 때

디자인 패턴의 과다한 사용은 불필요하게 복잡한 코드를 초래한다.


안티 패턴

1. 싱글톤

싱글톤이 안티패턴인 이유?

  • 상속이 불가능하다.

  • 테스트가 어려워진다.
    Mocking은 기본적으로 상속을 이용하는 것이므로 테스트를 하기 어려워지게 된다.
    cf) 스프링- 싱글톤 레지스트리
    자바에서 싱글톤을 직접 구현할 일은 거의 없다.

2. optional 사용

  • Null 체크시, Optional 사용을 자제하자.
1
2
3
4
5
6
7
8
9
String str = "";
Optional o = Optional.of(str);
// get() 메서드는 비어있는 Optional 객체를 대상으로 호출하면, 예외를 발생시킨다.
// 따라서, 객체의 존재 여부를 bool 타입으로 반환하는
// isPresent()라는 메소드를 통해 null 체크를 한다.
if (o.isPresent()) {
o.get();
}
o.map().map().map();

위의 코드는 Optional을 이용해서 Null 체크를 하는 경우이다.
이 코드가 하고 있는 Null 체크는 간단하게 아래와 같이 바꿀 수 있다.

1
2
3
4
String str = "";
if (str != null) {
str;
}

Optional을 어쩔 수 없이 써야하는 경우가 아니라면, 사용을 자제하자.


추천 도서

  • GoF의 디자인 패턴