- 정적 팩터리 메서드는 클래스에 정적 메서드를 정의하여, 생성자 대신 객체를 생성할 수 있게 만드는 기법이다.
장점 1. 이름을 가진 생성자
생성자는 기본적으로 이름을 가질수 없다.
아래와 같은 클래스가 존재한다고 했을때, 다른 개발자가 해당 생성자를 보고 코드를 직관적으로 이해할 수 있을까?
public class Test {
private int no;
private String name;
public Test(int no) {
this.no = no;
}
public Test(String name) {
this.name = name;
}
}
Test test1 = new Test(1);
Test test2 = new Test(2);
이렇게 코드를 작성하면, 다른 개발자가 생성자 인자에 no, name을 전달해야한다는 사실을 직관적으로 이해할 수 없다.
정적 팩터리 메서드를 사용한 객체 생성
public class Test {
private int no;
private String name;
private Test(int no, String name) {
this.no = no;
this.name = name;
}
public static Test createById(int id) {
return new Test(id, null);
}
public static Test createByName(String name) {
return new Test(0, name);
}
}
생성자에 private 접근 제어자를 두어 new 키워드로 직접 객체를 생성할 수 없게 하고, 정적 메서드를 통해 Book 객체를 생성한 뒤 반환하게한다.
Test test1 = Test.createById(1);
Test test2 = Test.createByName("이름");
이로서 생성자는 이름을 가지게 되고, 좀 더 직관적으로 바뀌게 된다.
장점 2. 호출될때마다 인스턴스를 생성하지 않아도 된다.
public class Test {
private int no;
private String name;
private Test(int no, String name) {
this.no = no;
this.name = name;
}
private static final Test TEST_INSTANCE = new Test(1, "test");
public static Test getInstance() {
return TEST_INSTANCE;
}
}
장점 3. 호출될때마다 인스턴스를 생성하지 않아도 된다.
class Parent {
public static Parent child1() {
return new Child1();
}
public static Parent child2() {
return new Child2();
}
public static Parent child3() {
return new Child3();
}
}
class Child1 extends Parent {
// ...
}
class Child2 extends Parent {
// ...
}
class Child3 extends Parent {
// ...
}
장점 4. 인자에 따라 다른 클래스 객체 반환 가능 (장점3과 비슷함)
장점 5. 정적 팩터리 메서드를 작성하는 시점에는 반환할 객체의 클래스가 존재하지 않아도 된다.
- 서비스 제공자 프레임워크를 만드는 근간이 된다. (ex. JDBC)
public static void main(String[] args) {
ServiceLoader<HelloService> loader = ServiceLoader.load(HelloService.class);
// 첫번째 구현체를 가져옴(있을수도 없을수도 optional로 가져옴
Optional<HelloService> helloServiceOptional = loader.findFirst();
helloServiceOptional.ifPresent(h -> {
System.out.println(h.hello());
});
}
단점1. 상속을 하려면 public이나 protected 생성자가 필요하니, 정적 팩토리 메소드만 제공하면 하위 클래스를 만들 수 없다.
위의 예제처럼 생성자를 private로 생성하기 때문에 상속받을 수 없다는 단점이 있다.