Q. 클래스의 인스턴스를 어떻게 얻을 수 있나요?
A. 클래스의 public 생성자를 통해 생성합니다!!
보통의 경우 생성자를 이용해 인스턴스를 생성해서 사용한다.
Item item = new Item();
또 다른 방법으로 생성자 대신 정적 팩터리 메서드(static factory method)를 사용하여 인스턴스를 제공할 수 있다.
private Item() {}; // 생성자를 통한 인스턴스 생성은 막아 주는 것이 좋다.
public static Item newInstance() {
return new Item();
}
이렇게 생성자 말고 정적 메소드를 사용하여 인스턴스를 생성 했을 때 어떤 이점이 있을까?
public class Item {
private String name;
private boolean important;
public Item(String name, boolean important) {
this.name = name;
this.important = important
}
}
public class Item {
private String name;
private boolean important;
public static Item normalItem(String name) {
Item item = new Item()
item.name = name;
item.important = false;
return item;
}
public static Item importantItem(String name) {
Item item = new Item()
item.name = name;
item.important = true;
return item;
}
}
Item item = new Item("name", true); // 생성자
Item item = Item.importantItem("name"); // 정적 메소드
public class Item {
private static final Item INSTANCE = new Item(); // 미리 생성
public class Item newInstance() {
return new Item(); // 새로 생성
}
public class Item getInstance() {
return INSTANCE; // 미리 생성한 인스턴스 반환
}
}
public interface Item {
// 하위 클래스를 반환 할 수 있다.
static Item newInstance() {
return new ImportantItem();
}
}
public class ImportantItem implements Item {
...
}
public interface Item {
String type();
// 매개 변수에 따라 하위 타입 객체를 선택하여 반환할 수 있다.
static Item of(boolean important) {
return important ? new ImportantItem() : new NormalItem();
}
}
public class ImportantItem implements Item {
@Override
public String type() {
return "important";
}
}
public class NormalItem implements Item {
@Override
public String type() {
return "normal";
}
}
public interface Item {
String type();
static Item getInstance() {
// Item 타입의 클래스를 불러온다. ImportantItem, NormalItem 클래스가 로드 된다.
ServiceLoader<Item> serviceLoader = ServiceLoader.load(Item.class);
// 해당 타입이 없을 수도 있기 때문에 Optional 이다.
Optional<Item> item = serviceLoader.findFirst();
return item.get();
}
}
public class ImportantItem implements Item {
@Override
public String type() {
return "important";
}
}
public class NormalItem implements Item {
@Override
public String type() {
return "normal";
}
}
Date d = Date.from(instant);
Set<Rank> faceCards = EnumSet.of(JACK, QUEEN, KING);
BigInteger prime = BigInteger.valueOf(Integer.MAX_VALUE);
StackWalker luke = StackWalker.getInstance(options);
Object newArray = Array.newInstance(classObject, arrayLen);
FileStore fs = Files.getFileStore(path);
BufferedReader br = Files.newBufferedReader(path);
List<Complaint> litany = Collections.list(legacyLitany);
정적 팩터리 메서드와 public 생성자는 각자의 쓰임새가 있으니 상대적인 장단점을 이해하고 사용하는 것이 좋다. 그렇다고 하더라도 정적 팩터리를 사용하는 게 유리한 경우가 더 많으므로 고려하는 것이 좋다.