728x90
staticName이라는 옵션을 사용하여 생성자를 private으로 생성하고, private 생성자를 감싸고 있는 static factory 메소드를 추가할 수 있다.
// 롬복코드
@AllArgsConstructor(staticName = "of")
public class TestDTO {
private int price;
private int discount;
private final int amount;
}
// 자바 코드
@Getter
public class TestDTO {
private int price;
private int discount;
private final int amount;
private TestDTO(int amount){
this.amount = amount;
}
public static TestDTO of(int i) {
return new TestDTO(i);
}
}
private 생성자가 생성되고, private 생성자를 감싸는 static factory 메소드가 생성
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
class TestDTOTest {
@Test
public void test1(){
TestDTO testDTO = TestDTO.of(4);
assertNotNull(testDTO);
assertEquals(0, testDTO.getPrice());
assertEquals(0, testDTO.getDiscount());
assertEquals(4, testDTO.getAmount());
System.out.println("testDTO.getPrice() = " + testDTO.getPrice());
System.out.println("testDTO.getDiscount() = " + testDTO.getDiscount());
System.out.println("testDTO.getAmount() = " + testDTO.getAmount());
}
}
정적 팩토리 메소드의 장단점
- 장점
- 이름이 있으므로 생성자에 비해 가독성이 좋다.
- 호출할 때마다 새로운 객체를 생성할 필요가 없다.
- 하위 자료형 객체를 반환할 수 있다.
- 형인자 자료형(parameterized type) 객체를 만들 때 편하다.
- 단점
- 정적 팩토리 메서드만 있는 클래스라면, 생성자가 없으므로 하위 클래스를 못 만든다.
- 정적 팩토리 메서드는 다른 정적 메서드와 잘 구분되지 않는다. (문서만으로 확인하기 어려울 수 있음)
//하위 자료형 객체를 반환
class OrderUtil {
public static Discount createDiscountItem(String discountCode) throws Exception {
if(!isValidCode(discountCode)) {
throw new Exception("잘못된 할인 코드");
}
// 쿠폰 코드인가? 포인트 코드인가?
if(isUsableCoupon(discountCode)) {
return new Coupon(1000);
} else if(isUsablePoint(discountCode)) {
return new Point(500);
}
throw new Exception("이미 사용한 코드");
}
}
class Coupon extends Discount { }
class Point extends Discount { }
//출처 https://johngrib.github.io/wiki/static-factory-method-pattern/
할인 코드의 규칙에 따라 Coupon과 Point 객체를 선택적으로 리턴하고 있다.
이를 위해서는 두 하위 클래스가 같은 인터페이스를 구현하거나, 같은 부모 클래스를 갖도록 하면 된다.
만약 파일을 분리하기 애매한 작은 클래스가 있다면 private class를 활용할 수도 있다.
다음은 java.util.Collections에서 EMPTY_MAP 부분만 발췌한 것이다.
@SuppressWarnings("rawtypes")
public static final Map EMPTY_MAP = new EmptyMap<>();
/**
* Returns an empty map (immutable). This map is serializable.
*/
@SuppressWarnings("unchecked")
public static final <K,V> Map<K,V> emptyMap() {
return (Map<K,V>) EMPTY_MAP;
}
private static class EmptyMap<K,V> extends AbstractMap<K,V> implements Serializable {
/* 생략 */
}
EmptyMap 클래스는 java.util.Collections 내에 private static으로 선언되었으며, emptyMap이라는 정적 팩토리 메서드를 통해 캐스팅된 인스턴스를 얻을 수 있다.
728x90
'Java 웹 프로그래밍' 카테고리의 다른 글
호다닥 정리할것들 모음 (0) | 2021.05.08 |
---|---|
백기선 자바스터디 10주차 (1) | 2021.02.27 |
[백기선 온라인 스터디] 3주차 과제 (0) | 2021.02.02 |
[백기선 온라인 스터디] 2주차 과제 (0) | 2021.01.27 |
[백기선 온라인 스터디] 1주차 과제 - JVM은 무엇이며 자바 코드는 어떻게 실행하는 것인가 (0) | 2020.11.15 |