정적 팩토리 (Static Factory)
간단한 팩토리를 정적 메서드로 정의하는 기법도 널리 사용되며, 이를 정적 팩토리라고 한다.
정적 팩토리를 사용하면 클래스는 클라이언트에게 public 생성자 대신 정적 팩토리 메서드를 제공할 수 있다.
장점
1. 이름을 가질 수 있다.
객체를 생성함에 있어 보다 명시적인 선언이 가능하다.
한 클래스에서 생성자를 오버로딩 하여, 인수로 전달받는 타입에 따라 구현을 달리 했다고 가정하자.
// 예시
class Book {
private Long bookCode;
private String bookName;
public Book(Long bookCode) {
this.bookCode = bookCode;
this.bookName = "책 제목";
}
public Book(String bookName) {
this.bookCode = 1335L;
this.bookName = bookName;
}
}
구현한 생성자를 이용하여 책 객체를 생성하려고 할 때, 전달해야 하는 인자에 대한 정보를 직관적으로 알기 어렵다.
하지만, 정적 팩토리 메서드를 이용하면 이름에 어떤 값을 필요로 하는지 명시할 수 있다.
// 예시
class Book {
private Long bookCode;
private String bookName;
private Book(Long bookCode, String bookName) {
this.bookCode = bookCode;
this.bookName = bookName;
}
public static Book createBook(Long bookCode, String bookName) {
return new Book(bookCode, bookName);
}
public static Book createBookByCode(Long bookCode) {
return new Book(bookCode, "책 제목");
}
public static Book createBookByName(String bookName) {
return new Book(1335L, bookName);
}
}
2. 호출될 때마다 새로운 인스턴스를 새로 생성하지 않아도 된다. (인스턴스 제어)
필요한 중복 객체 생성을 피할 수 있다.
따라서, 클래스가 싱글톤이거나 인스턴스화할 수 없음을 보장할 수 있다.
- 간단한 싱글톤 객체를 만들 수 있다.
불필요한 중복 객체 생성을 피하기 위해,
생성한 인스턴스를 캐시하여 반복적으로 제공할 수 있다.
위의 Book 클래스에 getBookInstance() 메서드를 추가하여, 이미 생성된 인스턴스를 반환할 수 있다.
3. 반환 타입의 하위 타입 객체를 반환할 수 있다.
반환할 객체의 클래스를 자유롭게 선택할 수 있는 유연성을 갖출 수 있다.
즉, 구상 클래스를 공개하지 않은 채로 리턴 타입을 상속 받은 모든 객체를 반환할 수 있다.
자바 8부터 인터페이스에서도 정적 메서드 선언이 가능하다. |
4. 입력 매개변수에 따라 매번 다른 클래스의 객체를 반환할 수 있다.
매개변수에 따라(상황에 따라) 반환하는 객체를 설정하여,
매번 다른 객체를 반환할 수 있다.
5. 정적 팩토리 메서드를 작성하는 시점에는 반환할 객체의 클래스가 존재하지 않아도 된다.
인터페이스나 클래스가 만들어 지는 시점에서 하위 타입의 클래스가 존재 하지 않아도 된다.
추후에 해당 인터페이스나 클래스를 상속 받는 클래스가 만들어지면, 의존성을 주입 받아서 사용할 수 있다.
반환값이 인터페이스여도 되며, 정적 팩터리 메서드의 변경 없이 구현체를 바꿀 수 있다.
단점
1. 상속을 하려면 public 이나 protected 생성자가 필요한데, 정적 팩터리 메서드만 제공하면 하위 클래스를 만들 수 없다.
서브 클래스를 만들어 객체 생성 메서드의 행동을 변경할 수 없다는 단점이 있다.
이 단점은 다른 측면에서 장점이 될 수도 있으며, 이펙티브 자바에서 Iten 17, 18에 서술되어 있다. (생략한다!)
2. 정적 팩터리 메서드는 프로그래머가 찾기 어렵다.
API문서에 명확히 드러내지 않기 때문에, 개발자가 직접 문서를 찾아야한다.