[자바] 정적 팩토리 메서드 static factory method

Kyu·2021년 2월 18일
0

Java 공부기록

목록 보기
32/40

생성자 VS 정적 팩토리 메소드

String str = new String("kyu");
String str = String.valueOf("kyu");

기본적으로 둘을 코드로 사용할 때는 위와 같은 차이를 가진다. 두번쨰코드는 String의 valueOf() 라는 정적 메소드로 kyu 라는 문자열을 생성한 것이다.

언제 무엇을 사용해야 할까?

생성자를 통하지 않고 정적 팩토리 메서드를 사용하는 이유는 뭘까? 이펙티브 자바 1장에는 “Consider static factory methods instead of constructors” 라고 나온다고 한다. 그만큼 어떤 이점이 있기 때문에 정적 팩토리 메서드를 사용하는 것이다. 그렇다고 앞으로 생성자 대신에 전부 정적 팩토리 메서드를 사용하라는 말은 아닐 것이다.

정적 팩토리 메서드 이해하기

// 코드 1

public class User {
    
    private final String name;
    private final String email;
    private final String country;
    
    public User(String name, String email, String country) {
        this.name = name;
        this.email = email;
        this.country = country;
    }
    
    // standard getters / toString
}

코드 1은 그냥 일반적으로 생성자로 데이터를 받아서 객체를 생성하는 방식이다. 딱히 문제가 없어보인다.

그런데 country만 기본값으로 모두 Korea 를 가지게 하고 싶다면 어떨까? country를 상수로 바꾸고 생성자를 수정하던지, 애초에 생성자에 Korea 라고 붙이던지 어쨋든 리팩토링이 필요할 것이다.

아니면, 이때 코드 2처럼 정적 팩토리 메서드를 사용할 수 있다.

// 코드 2

public static User createWithDefaultCountry(String name, String email) {
    return new User(name, email, "Korea");
}

그리고 이 정적 팩토리 메소드를 사용해서 country 값이 Korea 로 할당된 객체를 다음 코드 3처럼 생성할 수 있다.

// 코드 3

User user = User.createWithDefaultCountry("Kyu", "kyu@gmail.com");

정적 팩토리 메서드 - 생성자 밖으로 로직을 옮기기

코드 1에서 봤던 User 클래스에서 어떤 기능을 구현하기 위해 생성자에 로직을 넣도록 요구되는 그런 일이 발생한다면, User 클래스는 결함이 있는 디자인으로 빠르게 썩어갈 것이다.

구체적으로 그런 일은 어떤 일인가? 예를 들어서 User 객체가 생성됐을 때마다, 생성된 시각을 기록하는 기능을 추가해주고 싶다면 어떨까?

만약에 생성자에 그 로직을 넣는다면 단일 책임 원칙을 어기게 된다. 단지, 필드를 초기화해주는 작업이 아니라 그보다 훨씬 더 많은 일을 하는 로직을 넣어줌으로써 굉장히 단단하게 결집되어 있는 생성자를 만들게 될 것이다.

이 때, 정적 팩토리 메서드를 사용해서 이 문제를 해결할 수 있다.

// 코드 4

public class User {
    
    private static final Logger LOGGER = Logger.getLogger(User.class.getName());
    private final String name;
    private final String email;
    private final String country;
    
    // standard constructors / getters
    
    public static User createWithLoggedInstantiationTime(
      String name, String email, String country) {
        LOGGER.log(Level.INFO, "Creating User instance at : {0}", LocalTime.now());
        return new User(name, email, country);
    }
}

정적 팩토리 메서드로 만들면서 생성자에 직접 로직을 넣는 형식보다 느슨한 형태의 결합 코드를 가지게 됐다.

다음 코드 5처럼 인스턴스를 생성할 수 있을 것이다.

// 코드 5

User user 
  = User.createWithLoggedInstantiationTime("Kyu", "kyu@gmail.com", "Korea");

참고
Java Constructors vs Static Factory Methods

profile
TIL 남기는 공간입니다

0개의 댓글