CastleJo의 개발일지

Limit Instantiation with Singleton (396)

|

개요

어떤 클래스의 인스턴스를 여러 개 생성해 사용하고 있는데 그로 인해 메모리 사용량이 너무 커지거나 시스템 성능이 저하된다면, 여러 개의 객체를 하나의 싱글턴 객체로 대체한다.


동기

바로 전 포스트에서 싱글턴 패턴은 정말 특정한 상황이 아니면 필요하지 않다고 했다. 하지만 다음의 특정한 상황의 경우 싱글턴 패턴을 고려해보자.

  • 시스템 성능에 대한 사용자의 불만이 높다.
  • 프로파일러를 통해 확인한 결과, 객체를 반복적으로 생성하는 것이 시스템 성능에 악영향을 미친다.
  • 공유하려는 객체가 상태를 갖지 않거나, 갖더라도 상태를 공유할 수 있다.
장점
  • 성능을 향상시킨다.
단점
  • 어느 곳에서나 객체를 접근할 수 있게 된다. 많은 경우, 이는 좋지 않은 설계로 평가된다.
  • 객체를 공유하면 안 되는 상태가 존재할 때에는 적용할 수 없다.


절차

이 리팩터링을 적용하기 전에, 대상이 되는 객체에 상태가 없거나 있더라도 공유가 가능한지 확인해야 한다.

  1. 인스턴스를 여러 개 가지는 클래스. 즉, 하나 이상의 클라이언트에 의해 두번 이상 생성되는 클래스를 찾는다. 그 클래스에 Replace Constructor with Creation Methods을 적용한다. 생성자가 하나뿐인 경우라도 마찬가지다. 생성 메서드의 리턴 타입은 대상 클래스 타입이어야 한다.

  2. 싱글턴 필드를 만든다. 필드는 private static 타입으로, 타입은 대상 클래스 타입으로 선언한다. 가능하다면 대상 클래스의 인스턴스로 싱글턴 필드를 초기화한다.
    런타임에 클라이언트로부터 받아야 할 파라미터가 존재한다면 초기화할 수 없을 것이다. 이럴 경우 필드만 선언하고 초기화는 하지 않는다.

  3. 앞서 만든 생성 메서드가 싱글턴 필드의 값을 리턴하도록 수정한다. 단계 2에서 초기화를 하지 못했다면, 전달받은 파라미터를 이용해 이 생성 메서드에서 초기화를 수행하도록 한다.