정적 팩터리 메서드는 객체 생성 역할을 하는 클래스 메서드이다.
public class Car {
private String car;
// 생성자
public Car(final String car) {
this.car = car;
}
// 정적 팩터리 메서드
public static Car from(final String name) {
return new Car(name);
}
}
❗생성자 대신 정적 팩터리 메서드를 사용해야 하는 이유
‼장점 1. 이름을 가질 수 있다.
정적 팩터리 메서드를 사용하면, 메서드 이름에 객체의 생성 목적을 담아낼 수 있다.
public static Car createDefaultCar() {
return new Car("Default");
}
위와 같은 형식으로 객체를 생성하면, 어떤 객체가 생성되는지 좀 더 구체적으로 알 수 있다.
‼장점 2. 같은 타입의 다른 다른 파라미터를 받아 객체를 생성할 수 있다.
public class Person {
private String name;
private String address;
public Person(final String name) {
this.name = name;
}
public Person(final String address) {
this.address = address;
}
}
생성자는 같은 타입의 다른 파라미터를 받을 수 없어 위의 코드는 오류가 발생한다.
하지만, 정적 팩터리 메서드를 사용하면, 다음과 같이 코드를 변경할 수 있다.
public class Person {
private String name;
private String address;
public static Person withName(final String name) {
Person person = new Person();
person.name = name;
return person;
}
public static Person withAddress(final String address) {
Person person = new Person();
person.address = address;
return person;
}
}
‼장점 3. 호출될 때마다 새로운 인스턴스를 생성할 필요가 없다.
public class Number {
public static final int MIN_NUMBER = 1;
public static final int MAX_NUMBER = 100;
private static final Number[] NUMBER_CACHE = new Number[MAX_NUMBER + 1];
private int number;
static {
for (int number = MIN_NUMBER; number < MAX_NUMBER; number++) {
NUMBER_CACHE[number] = new Number(number);
}
}
public Number(final int number) {
this.number = number;
}
public static Number valueOf(final int number) {
if (number < MIN_NUMBER || number > MAX_NUMBER) {
throw new IllegalArgumentException();
}
return NUMBER_CACHE[number];
}
}
Number 객체는 사용자가 값을 요청할 때마다, 새로운 객체를 생성해주는 것보다 미리 만들어 놓은 객체를 제공하는 것이 더 효율적이다. 이때, 정적 팩터리 메서드를 사용할 수 있다.
미리 만들어 놓은 Number 객체를 사용자가에 제공함으로써, 객체를 생성하는 비용을 아낄 수 있고, 싱글톤 효과 역시 얻을 수 있다.
‼장점 4. 변환 타입의 하위 타입 객체를 반환할 수 있다.
public interface Dog {
public String bark();
}
public class Maltese implements Dog {
private String name;
@Override
public String bark() {
return "Wong!";
}
public Maltese(final String name) {
this.name = name;
}
public static Dog withName(final String name) {
return new Maltese(name);
}
}
위와 같이 코드를 만들게 되면, Dog dog = Maltese.withName("name")으로 객체를 생성할 수 있다. 이렇게 코드를 작성하게 되면, 인터페이스만 노출이 되므로 '개념적인 무게 줄이기'가 가능하다.
자바 8이후 부터는 interface에서 static method를 생성할 수 있다.
public interface Dog {
public String bark();
public static Dog from(final String name) {
return new Maltese(name);
}
}
❗Convensions
from: 하나의 매개 변수를 받아서 객체 생성
of: 여러 개의 매개 변수를 받아서 객체 생성
valueOf: from과 of의 더 자세한 버전
'이팩티브 자바' 카테고리의 다른 글
[Effective] equals & hashCode (0) | 2023.03.09 |
---|---|
[Effective] try-with-resources (1) | 2023.03.03 |