이번 포스팅은 이펙티브 자바에 나오는 토픽 중 "생성자 대신 정적 팩터리 메서드를 고려하라.
"라는 내용에 대해 포스팅하려고 합니다.
정적
이라는 말이 붙은 것으로 봐서 static을 사용한다는 것을 의미할 겁니다.팩토리
라는 표현은 객체를 생성하는 역할을 붙리하겠다는 의미가 있을 것 입니다.이러한 네이밍을 고려했을 때,
정적 팩토리 메서드는 객체 생성의 역할을 하는 메서드라고 볼 수 있습니다.
List<Integer> lists = List.of(1,2,3,4);
그렇다면 정적 팩토리 메서드가 왜 필요할까요? 그냥 생성자를 사용하면 되지 않을까요??
public class Order {
private boolean prime;
private boolean urgent;
private Product product;
private OrderStatus orderStatus;
//1과 2 생성자는 컴파일 오류가 난다.
//1
public Order(Product product, boolean urgent){
this.product = product;
this.urgent = urgent;
}
//2
public Order(Product product, boolean prime){
this.product = product;
this.prime = prime;
}
//정적 팩토리 메서드 사용
//3
public static Order primeOrder(Product product) {
Order order = new Order();
order.prime = true;
order.product = product;
return order;
}
//4
public static Order urgentOrder(Product product) {
Order order = new Order();
order.urgent = true;
order.product = product;
return order;
}
}
public class Settings {
private boolean useAutoSteering;
private boolean useABS;
private Difficulty difficulty;
private Settings() {}
private static final Settings SETTINGS = new Settings();
public static Settings getInstance() {
return SETTINGS;
}
}
public interface HelloService {
String hello();
}
public class EnglishHelloService implements HelloService{
@Override
public String hello() {
return "hello";
}
}
public class KoreaHelloService implements HelloService{
@Override
public String hello() {
return "안녕";
}
}
public class HelloServiceFactory {
public static HelloService of(String language){
if(language.equals("kor")){
return new KoreaHelloService();
}
return new EnglishHelloService();
}
}
---------------------------------------------------------
public static void main(String[] args) {
HelloService kor = HelloServiceFactory.of("kor");
System.out.println(kor instanceof KoreaHelloService);//true
System.out.println(kor.hello());//안녕
HelloService eng = HelloServiceFactory.of("eng");
System.out.println(eng instanceof EnglishHelloService); //true
System.out.println(eng.hello()); //hello
}
서비스 제공자 프레임워크(service provider framework)에서 서비스를 제공하는 제공자(provider)는 서비스의 구현체다. 이 구현체들을 클라이언트에 제공하는 역할을 프레임워크가 통제하여, 클라이언트를 구현체로부터 분리해준다.
여기서 중요한 것은 클라이언트를 구현체로부터 분리해준다.
라는 말이 핵심인 것 같습니다.서비스 제공자 인터페이스
: 어떤 서비스를 확장가능하도록 만들 것이냐에 초점을 맞춤니다. 여러 구현체를 가질 수 있겠죠?서비스 제공자
: 서비스를 구현한 것을 의미합니다.서비스 제공자 등록 api
: 서비스 구현체를 등록하는 방법을 제공합니다. (스프링에서 @Configuration, @Bean 등등)서비스 접근 api
: 클라이언트에서 서비스를 가지고 오는 방법을 제공합니다. (@Autowired 등등)ServiceLoader
클래스의 load
라는 정적 팩토리 메서드를 사용한다고 했을 때, ServiceLoader<HelloService> loader = ServiceLoader.load(HelloService.class);
Optional<HelloService> helloServiceOptional = loader.findFirst();
helloServiceOptional.ifPresent(h -> {
System.out.println(h.hello()); //ni hao
});
reference