코드를 보면 of, from 등 static 메서드를 많이 본 적이 있다. 정적 팩토리 메서드를 사용하면서 장점과 유의할 점에 대해서 알아보자
new Store(a, b, c) < - > Store.newInstance(a, b, c)
생성자와는 다르게 네이밍을 지어줄 수 있기 때문에 의미 파악이 조금 더 쉽다.
불변 클래스의 경우 매번 인스턴를 새로 생성할 필요 없이 인스턴스를 캐싱하여 재활용하는 식으로 불필요한 객체 생성을 피할 수 있다.
그 예로 Boolean.vlaueOf를 들 수 있다. Boolean valueOf는 클래스 상수로 TRUE, FALSE 인스턴스를 생성하고, Boolean.valueOf를 호출하면 상수를 반환하기만 할 뿐 인스턴스를 생성하지 않는다. 이처럼 캐싱 전략을 이용해 불필요한 인스턴스를 생성하는 비용을 절약할 수 있다.
3번과 4번은 비슷하게 엮어서 설명이 가능할 것 같다. EnumSet의 경우 정적 팩터리만 제공하는데 EnumSet의 원소의 수의 따라 RegularEnumSet과 JumboEnumSet으로 나뉜다. 이들은 EnumSet을 상속받는데 상태에 따라 다형석을 활용해 다양한 리턴을 반환한다.
사실 정적 팩토리를 이용하면 쉽고 간결해서 코드를 짤 때 많이 애용했는데 네이밍 컨벤션까지 지키진 않았던 것 같다. 주로 정적 팩토리에서 많이 쓰이는 네이밍 컨벤션은 다음과 같다.
ex) Date d = Date.from(instance);
ex) Set<Rank> faceCards = EnumSet.of(JACK, QUEEN, KING);
ex) BigInteger prime = BIgInteger.valueOf(Integer.MAX_VALUE);
ex) StackWalker luke = StackWalker.getInstance(options);
create 혹은 newInstance: getInstance와 동일하게 사용하지만 매번 인스턴스를 생성한다는 점을 강조할 때 사용한다.
getType: getInstance와 같으나 다른 타입을 반환할 때 사용
FileStore fs = Files.getFileStore(path)
ex) BufferedReader br = Files.newBufferedReader(path);
ex) List<Complaint> litany = Collections.list(legacyLitany);