[Java] 정적 팩토리 메소드

이열음·2022년 2월 26일
3

정적 팩토리 메소드란?

생성자 기법과는 별도로 생성만을 담당하는 클래스 메소드를 의미합니다.
직접적인 생성자가 아닌 메소드를 통해 객체를 생성합니다.
외부에서 요청이 들어오면 이에 맞게 객체를 생성하거나, 단순반환해주는 것이 주된 역할입니다.

장점

이름이 명확하다

생성자와는 다르게 메소드로 객체를 생성하기 때문에 이름짓기의 자유도가 높습니다.

// 생성자
Public class Coke{
	public Coke(int sugar, int water){
    	어쩌구 저쩌구..
    };
}

// 정적 팩토리 메소드
public class Coke{
	public static Coke makeCokeBySugarAndWater(int sugar, int water){
    	어쩌구 저쩌구..
    }
}

변환에 있어 내부 구조를 캡슐화할 수 있다.

DTO변환 시 정적팩토리메소드를 사용한다면
from이나 of(외부객체를 해당 객체로 변환)를 사용하기만 하면 되지만,
인스턴스 메소드 사용시 생성자 자체와 그의 내부를 전부 노출시키게 됩니다.

// 인스턴스 메소드 사용시
CarDto carDto = new CarDto(car.getCarName,car.getCarDistance)

// 정적 팩토리 메소드 사용시
 CarDto carDto = CarDto.from(car)

시그니처를 다양하게 사용할 수 있다.

생성자는 매개변수의 갯수가 정해지면, 또 다른 생성자를 만들기 좀 애매합니다.
오버로딩을 이용해서 추가로 생성할 수는 있겠지만
이러면 다른 개발자가 생성자를 이해하기 어려워지기 때문입니다.

  • 앞서 언급되어있는 것 처럼 도메인 바깥에서 보면 도메인 이름만 있고
    어떤 파라미터가 필요한지는 도메인까지 가서 들여다봐야 함
  • 왜 생성자가 다중으로 있는지 작성자의 의도를 파악하기 어려움

이와달리 정적 팩토리 메소드는 다중생성자가 각각의 메소드로 파지게 되어
이름만 잘 지어주면 의도를 파악하기가 쉽습니다.

// 생성자
public class Coke{
	public Coke();
	public Coke(int sugar);
	public Coke(int water);
}

// 정적 팩토리 메소드
public class Coke{
	private Coke();
	public static Coke cokeOnlyWater(int water);
    public static Coke cokeOnlySugar(int sugar);
    public static Coke emptyCoke();
}

하위타입 반환 가능

해당 객체의 자식 객체를 생성 및 반환할 수 있다.
관련된 애들을 한곳에 다 때려박을 수 있고
분기문을 통해 조건부로 자식클래스 생성도 가능하다
ex) 콜라 인터페이스 생성 -> 코카콜라, 펩시 생성 구현체 작성 -> 각 타입별로 반환 가능

public interface Coke{
	public static Coke generateCocaCola(){
    	return new CocaCola();
    }
    
    public static Coke generatePepsi(){
    	return new Pepsi();
    }
    
}

public class CocaCola implements Coke{
}

public class Pepsi implements Coke{
}

물론 앞선 코드는 인스턴스 클래스에서도 가능한 코드입니다.
하지만 정적 팩토리 메서드를 사용하게 되면
인터페이스의 실제 구현 클래스를 노출시키지 않고도 생성이 가능하다는 장점이 있습니다.

ex) Coke.makeCocaCola(), 원래라면? CocaCola()

// 인스턴스 메소드 사용시 생성자 자체가 노출
new CocaCola();

// 정적 팩토리 메소드 사용시 실제 생성자(new)는 해당 메소드 안에 은닉되어있음. 
Coke.generateCocaCola(); 

또한 하위타입에 맞기만 하면 되므로
분기문 처리를 통해 반환하는 객체를 달리할수도 있습니다.


public class Coke{
	... 
	public Coke of(String name){
    	if(name.equals("CocaCola"){
        	return new CocaCola();
        }
        if(name.equals("Pepsi"){
        	return new Pepsi();
        }
    }
    
    // 이런것도 가능하다.
    public Coke of(boolean sugar){
    	return sugar?  new CocaCola() : new ZeroCola();
    }
    
}

단점

상속 불가능

정적 팩토리 메서드를 사용할 시 생성자는 접근제어자가 private으로 한정되어 있기 때문에 해당 클래스는 부모 클래스가 될 수 없습니다. (근데 역으로 생각하면 생성자 제어 할 수 있어서 오히려 좋은 경우도 있습니다.)

상대적으로 생성자를 찾기가 쉽지 않음

인스턴스 클래스라면 포멧이 생성자, 메소드1, 메소드2 이런식으로 가는데
정적 팩토리 메서드를 쓰면 생성자도 일반적인 메소드와 같은 형식이여서
상대적으로 찾기가 좀 어렵습니다.

결론

결론적으로 해당 방식은 가독성과 객체 생성에 있어서는 장점이 많습니다.
특히 생성에 많은 기능이 들어가거나, 형변환이 있는 클래스라면
한번 고려해봐도 좋을 것 같네요.

https://velog.io/@ljinsk3/%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%8A%94-%EC%99%9C-%EC%82%AC%EC%9A%A9%ED%95%A0%EA%B9%8C
https://devlog-wjdrbs96.tistory.com/256

0개의 댓글