본문 바로가기
Java

[Java] 정적 팩토리 메서드 (Static Factory Method)

by 도전하는 린치핀 2024. 7. 15.

 

1. 정적 팩토리 메서드 (Static Factory Method)란?

  • 정적 팩토리 메소드는 개발자가 구성한 Static Method를 통해 간접적으로 생성자를 호출하여 객체를 생성하는 패턴
  • 보통 객체를 인스턴스화 할 때, 생성자를 호출하며 객체를 생성하는데 생성자에는 다양한 단점이 존재할 수 있다.
  • 이를 해결하기 위해, 객체 생성을 담당하는 메소드를 정적 팩토리 메서드라고 한다.
  • 정적 팩토리 메서드는 이름에서 알 수 있듯이 GOF의 팩토리 메서드, 추상 팩토리 패턴에서의 팩토리 개념을 따온 것이라고 생각할 수 있다.

자바에서 '생성자 대신 정적 팩토리 메서드를 고려하라' 라는 말이 있을 정도로 정적 팩토리 메서드는 객체를 생성할 때, 꽤나 중요해 보인다.

 

생성자를 왜 사용하지 말고 더 나아가 정적 팩토리 메서드를 통해 객체를 생성하는지 의문이 들었다.

하지만 실제 정적 팩토리 메서드의 경우 단순히 생성자의 역할을 대신하는 것이 아닌 코드의 가독성을 향상시키고 객체 지향적 프로그래밍에 더욱 가까워질 수 있는 방법이다.

 

2. 정적 팩토리 메서드 (Static Factory Method) 장단점

2-1. 장점

장점 1. 이름을 가질 수 있어 가독성이 좋다.

  • 기존 생성자를 통한 객체 생성에는 생성 목적에 따른 생성자 오버로딩을 통해 구분하여 객체를 생성하였다.
  • 하지만 이것은 객체를 생성할 때, 개발자가 생성자의 매개변수 순서, 내부 구조를 정확히 알아야 목적에 맞는 객체를 생성할 수 있다는 문제가 발생한다.
  • 즉, 생성자를 통해 객체를 설계할 때는 매개변수만으로 반환될 객체의 특정을 제대로 표현하기 어렵다.
  • 이것은 객체 지향적인 측면과 코드의 가독성과 효율성 측면에서 매우 큰 단점이 될 수 있다.
  • 하지만 정적 팩토리 메서드는 적절한 메서드 이름을 통해 객체의 생성 목적과 객체의 특성을 담아 낼 수 있다.
  • 생성자 대신 정적 팩토리 메서드를 호출함으로써 생성될 객체의 특성에 대해 쉽게 묘사할 수 있다는 장점이 있어 코드의 가독성을 높여주게 된다. 
  • 더 나아가 정적 팩토리 메서드를 구성할 때, private 생성자를 두어 외부에서 new 키워드로는 접근할 수 없지만 객체 내부에서 생성자를 통해 객체를 생성하게 하는 방법도 있다.

 

장점 2. 호출 할 때마다 새로운 객체를 생성할 필요가 없다.

  • 메서드를 통해 한단계 거쳐 간접적으로 객체를 생성하기 때문에, 기본적으로 전반적인 객체 생성 및 통제 관리를 할 수 있게 된다.
  • 즉, 필요에 따라 항상 새로운 객체를 생성해서 반환할 수도 있고, 아니면 객체 하나만 만들어두고 이를 공유하여 재사용하게 하여 불필요한 객체를 생성하는 것을 방지 할 수 있는 것이다.
  • 대표적인 예로 Singleton 디자인 패턴을 통한 하나의 객체만 반환하도록 하여 객체를 재사용하여 메모리를 아끼는 방법이 있다.
  • 또다른 예로는 인스턴스에 대한 캐싱(Caching) 절차 구조를 정적 팩토리 메서드로 구현할 수 있다. 인스턴스에 대해 캐싱을 한다면 필요한 인스턴스만 뽑아 재사용하여 메모리를 절약할 수 있게 된다.

 

장점 3. 하위 자료형 객체를 반환할 수 있다

  • 클래스의 다형성의 특징을 응용한 정적 팩토리 메서드 특징이다.
  • 즉, 메서드 호출을 통해 얻을 객체의 인스턴스를 자유롭게 선택할수 있는 유연성을 갖는 장점이 생긴다.
  • 이것은 인터페이스 기반의 프레임워크를 사용할 수 있게 해준다.
  • 대표적으로 자바의 컬렉션 프레임워크인 java.util.Collections 클래스를 들 수 있는데, 이 클래스는 Collection 인터페이스를 반환하는 여러 정적 팩토리 메서드를 가지고 있다.

 

장점 4. 입력 매개변수에 따라 매번 다른 클래스의 객체를 반환할 수 있다.

  • 메서드 블록 내에서 분기문을 통해 여러 자식 타입의 인스턴스를 반환하도록 응용 구성이 가능하다
  • 위의 3번에서 설명한 하위 자료형 객체를 반환하는 것과 비슷한 개념이다.
  • 만약 특정 인터페이스를 상속 받은 구현체가 있을 때, 객체 생성 시 상황에 따라 유동적으로 해당하는 구현체 타입으로 반환할 수 있다.

 

장점 5. 객체 생성을 캡슐화할 수 있다.

  • DTO와 Entity간에는 자유롭게 형 변환이 가능해야 하는데, 정적 팩터리 메서드를 사용하면 내부 구현을 모르더라도 쉽게 변환할 수 있다.
  • 만약 정적 팩토리 메서드를 쓰지 않고 DTO로 변환한다면 외부에서 생성자의 내부 구현을 모두 드러낸 채 해야할 것이다.

 

2-2. 단점

단점 1. private 생성자일 경우 상속 불가능

  • 정적 팩토리 메서드는 생성자로 인스턴스를 생성하는 것을 막기 위해 생성자 접근 제어자를 private로 설정한다.
  • 이때, 생성자가 private이기 때문에 해당 생성자에 접근할수가 없어 상속이 불가능하다는 문제가 생긴다.
  • "상속 보단 합성" 원칙을 보면 상속에 대해 단점과 한계에 대해 많이 설명하고 있고, 상속보다는 합성을 사용하는 것을 권장하기 때문에, 첫번째 단점은 무조건적인 단점이라고 할 수 없다.

 

단점 2. 정적 팩토리 메서드를 다른 개발자들이 찾기 어렵다.

  • 개발자가 임의로 만든 정적 메서드이기 때문에 다른 개발자가 사용 시 찾아 사용하기 어려울 수 있다.
  • 하지만 이 단점도 아래 소개할 정적 팩토리 메서드 네이밍 컨벤션을 따르며 API 문서를 잘 작성한다면 어느정도 해결 할 수 있는 부분이다.

 

3. 정적 팩토리 메서드 네이밍 컨벤션

  • from : 하나의 매개변수를 받아 해당 타입의 인스턴스를 반환하는 형변환 메서드 
  • of : 여러 매개변수를 받아 적합한 타입의 인스턴스를 반환하는 집계 메서드
  • valueOf : from과 Of의 더 자세한 버전
  • instance | getInstance : 매개변수로 명시한 인스턴스를 반환하며, 이전 인스턴스와 같은 인스턴스임을 보장 하지 않음
  • create | newInstance : instance | getInstance 와 같으나 항상 새로운 인스턴스를 생성해 반환 함을 보장함
  • get[OrderType] : 다른 타입의 인스턴스를 생성하여 이전 인스턴스와 같은 인스턴스임을 보장하지 않음
  • new[OrderType] : get[OrderType]과 같이 다른 타입을 반환하지만 항상 새로운 인스턴스임을 보장

예시 코드를 통해 확인해보자.

// from : 매개변수를 하나 받아서 해당 타입의 인스턴스를 반환하는 형변환 메서드
Date d = Date.from(instant);

// of : 여러 매개변수를 받아 적합한 타입의 인스턴스를 반환하는 집계 메서드
Set<Rank> faceCards = EnumSet.of(JACK, QUEEN, KING);

// valueOf : from과 of의 더 자세한 버전
BigInteger prime = BigInteger.valueOf(Integer.MAX_VALUE);

// instance 혹은 getInstance : (매개변수를 받는다면) 매개변수로 명시한 인스턴스를 반환하지만, 같은 인스턴스임을 보장하지는 않는다.
StackWalker luke = StackWalker.getInstance(options);
Calendar instance = Calendar.getInstance();

// create 혹은 newInstance : instance 혹은 getInstance와 같지만, 매번 새로운 인스턴스를 생성해 반환함을 보장한다.
Object newArray = Array.newInstance(classObject, arrayLen);

// getType : getInstance와 같으나, 생성할 클래스가 아닌 다른 클래스에 팩터리 메서드를 정의할 때 쓴다. Type은 팩터리 메서드가 반환할 객체의 타입이다.
FileStore fs = Files.getFileStore(path);

// newType : newInstance와 같으나, 생성할 클래스가 아닌 다른 클래스에 팩터리 메서드를 정의할 때 쓴다. Type은 팩터리 메서드가 반환할 객체의 타입이다.
BufferedReader br = Files.newBufferdReader(path);

 

 

더보기

Ref

https://mysterlee.tistory.com/55

 

정적 팩토리 메서드(Static Factory Method)

패스트 캠퍼스의 강의를 듣던 중 정적 팩토리 메서드를 사용하는 상황을 보았다. 처음 보는 객체 생성 방식이길래 찾아보던 중 이것이 정적 팩토리 메서드라는 것을 알게 되었고, 관련 내용을

mysterlee.tistory.com

https://velog.io/@cjh8746/%EC%A0%95%EC%A0%81-%ED%8C%A9%ED%86%A0%EB%A6%AC-%EB%A9%94%EC%84%9C%EB%93%9CStatic-Factory-Method

 

정적 팩토리 메서드(Static Factory Method)

정적 팩토리 메서드란 무엇인가?

velog.io

 

https://hstory0208.tistory.com/entry/OOP-%EC%A0%95%EC%A0%81-%ED%8C%A9%ED%86%A0%EB%A6%AC-%EB%A9%94%EC%84%9C%EB%93%9C%EB%A5%BC-%EC%99%9C-%EC%82%AC%EC%9A%A9%ED%95%98%EB%8A%94%EA%B0%80-%EC%96%B4%EB%96%A4-%EC%83%81%ED%99%A9%EC%97%90-%EC%82%AC%EC%9A%A9%ED%95%98%EB%8A%94%EA%B2%8C-%EC%A2%8B%EC%9D%84%EA%B9%8C-%EC%83%9D%EC%84%B1%EC%9E%90%EC%99%80-%EC%B0%A8%EC%9D%B4

 

[OOP] 정적 팩토리 메서드를 왜 사용하는가? 어떤 상황에 사용하는게 좋을까? (생성자와 차이)

정적 팩토리 메서드란? 쉽게 말해 생성자로 인스턴스를 생성하지 않고, static Method를 사용해 인스턴스를 생성하는 방식이다. 간단한 예시로 여러 장르(genre)를 가지는 게임(Game) 객체에 대한 코드

hstory0208.tistory.com

 

https://tecoble.techcourse.co.kr/post/2020-05-26-static-factory-method/

 

정적 팩토리 메서드(Static Factory Method)는 왜 사용할까?

tecoble.techcourse.co.kr

 

https://inpa.tistory.com/entry/GOF-%F0%9F%92%A0-%EC%A0%95%EC%A0%81-%ED%8C%A9%ED%86%A0%EB%A6%AC-%EB%A9%94%EC%84%9C%EB%93%9C-%EC%83%9D%EC%84%B1%EC%9E%90-%EB%8C%80%EC%8B%A0-%EC%82%AC%EC%9A%A9%ED%95%98%EC%9E%90

 

💠 정적 팩토리 메서드 패턴 (Static Factory Method)

Static Factory Method Pattern 정적 팩토리 메서드(Static Factory Method) 패턴은 개발자가 구성한 Static Method를 통해 간접적으로 생성자를 호출하는 객체를 생성하는 디자인 패턴이다. 우리는 지금까지 객체

inpa.tistory.com

 

 

'Java' 카테고리의 다른 글

[Java] Java 예외 처리  (0) 2024.03.19