본문 바로가기
Java 웹 프로그래밍

AllArgsConstructor, RequiredArgsConstructor에 staticName 옵션을 이용한 static factory 메소드 생성

by irerin07 2021. 2. 14.
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());

    }
}

 

 

정적 팩토리 메소드의 장단점

  • 장점
    1. 이름이 있으므로 생성자에 비해 가독성이 좋다.
    2. 호출할 때마다 새로운 객체를 생성할 필요가 없다.
    3. 하위 자료형 객체를 반환할 수 있다.
    4. 형인자 자료형(parameterized type) 객체를 만들 때 편하다.
  • 단점
    1. 정적 팩토리 메서드만 있는 클래스라면, 생성자가 없으므로 하위 클래스를 못 만든다.
    2. 정적 팩토리 메서드는 다른 정적 메서드와 잘 구분되지 않는다. (문서만으로 확인하기 어려울 수 있음)
//하위 자료형 객체를 반환
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