북극곰의 개발일기

chapter1 정적 팩토리 메소드





posted by purplebeen on Sat Feb 03 2018 21:13:22 GMT+0900 (KST) in JAVA


규칙1

생성자 대신 정적 팩토리 메소드를 사용할 수 없는지 생각해 보라.

정적 팩토리 메소드의 예시

public static Boolean valueOf(boolean b) {
        return b ? Boolean.TRUE : Boolean.FALSE;
}

일반적인 디자인 패턴에서 말하는 디자인패턴과는 다소 차이가 있다.

정적 팩토리 메소드의 장점

  • 생성자와는 달리 정적 팩토리 메소드에서는 이름(name)이 있다.

  • 생성자와는 달리 호출할 때마다 새로운 객체를 생성할 필요가 없다.

    → 변경 불가능한 클래스라면 이미 만들어 둔 객체를 활용할 수도 있고, 만든 객체를 캐시 해놓고 재사용하여 같은 객체가 불필요하게 거듭 생성되는 일을 피할 수 있다.

  • 생성자와는 달리 반환값 자료형의 하위 자료형 객체를 반환할 수 있다.

  • 형인자 자료형 (parameterized type) 객체를 만들때 편하다.

서비스 제공자

  • 서비스 인터페이스 (service interface) : 서비스 제공자가 구현한다.

  • 제공자 등록 API (provider registration API) : 구현체를 시스템에 등록하여 클라이언트가 쓸 수 있도록 한다.

  • 서비스 접근 API (service access API) : 클라이언트에게 실제 서비스 구현체를 제공한다.

    → 결국 유연한 정적 팩토리이다.

// 서비스 제공자 인터페이스의 대략적인 모습

//서비스 인터페이스
public interface Service {
       // 서비스에 고유한 메소드들이 이 자리에 온다.
}

//서비스 제공자 인터페이스
public interface provider {
       Service newService();
}

//서비스 등록과 접근에 사용되는 객체 생성 불가 클래스 
public class Services {
       private Services() { } //객체 생성 방지
       
       //서비스 이름과 서비스 간 대응관계 보관
       private static final Map<String, Provider> providers = 
           new ConcurrentHashMap<String, Provider>();
       public static final String DEFAULT_PROVIDER_NAME = "<def>";
       
       //제공자 등록 API
       public static void registerDefaultProvider(Provider p) {
               registerProviders(DEFAULT_PROVIDER_NAME,p);
       }
   
       public static void registerProviders(String name, Provider p) {
               providers.put(name, p);
       }

       //서비스 접근 API
       public static Service newInstance(String name) {
               Provider p = providers.get(name);
               if(p == null) 
                   throw new IllegalArgumentException("No Provider with name : " + name);
               return p.newService();
       }
}

정적 팩토리 메소드의 단점

  • public이나 protected로 선언된 생성자가 없으므로 하위 클래스를 만들 수 없다.
  • 정적 팩토리 메소드가 다른 정적 메소드와 확연히 구분되지 않는다.

정적 팩토리 메소드의 명명 규칙

  • valueOf : 인자로 주어진 값을 갖는 객체를 반환. 형변환 (type-conversion) 메소드
  • of : valueOf를 간단하게 쓴 것
  • getInstance : 인자에 기술된 객체를 반환 하지만, 인자와 같은 값을 갖지 않을 수도 있다.
  • newInstance : getInstance와 같지만 호출할 때 마다 다를 객체를 반환한다.
  • getType : getInstance와 같지만, 반환될 객체의 클래스와 다른 클래스의 팩토리 메소드가 있을 때 사용한다.
  • newType : newInstance와 같지만, 반환될 객체의 클래스가 다른 클래스의 다른 팩토리 메소드에 있을 때 사용한다.