[TIL] 230123

✏️ Check Box

📌 정리


Effective 자바를 읽은 날 각 아이템에 대해 드는 생각들은 TIL로 정리해보려한다.

아이템1. 생성자 대신 정적 팩토리 메서드를 고려하라.

부트캠프 스프링 강의중 강사님께서 사용하신 예를 본 적은 있었다. 하지만 정확한 개념을 몰랐기에 사용은 하지 않았다.

  1. 한번쯤은 고민했을 법한 생성자가 많아진다면 매개변수 만으로 구분해야하는데 쉽지 않다는 것이다. 하지만 정적 팩토리 메서드는 이름을 가지는 메서드를 통해 인스턴스를 생성하기에 제약이 없다.
  2. 불변 클래스의 인스턴스를 매번 새로 생성하지 않고, 캐싱하는 방식으로 사용할 수 있다.
  3. Collections와 같은 동반 클래스에서 하위 타입의 객체를 반환할 수 있었던 것처럼 유연성을 부여할 수 있다.
  4. 메서드이기에 각 팩토리 메서드마다 다른 클래스의 객체를 반환할 수 있다.

public 생성자도 각 쓰임새가 있겠지만 정적 팩토리메서드 사용이 유리한 경우가 많다고 한다.

무심코 사용했던 from, of, valueOf, newType 등이 정적 팩토리 메서드였다는 것을 생각해보니 코드만 치기에 급급했던 내가 참 바보같았다…

아이템2. 생성자에 매개변수가 많다면 Builder를 고려하라.

Lombok을 통해 접했던 Builder 패턴이다. 이미 장점을 알고 있었지만 Lombok이 자동으로 구현해주므로 직접 코드를 작성해본 적은 없었다… 책에 작성된 코드와 Lombok이 생성한 코드를 비교해보았다.


public class Test {
    private final int v1;
    private final int v2;
    private final int v3;

    public Test(int v1, int v2, int v3) {
        this.v1 = v1;
        this.v2 = v2;
        this.v3 = v3;
    }

    public static TestBuilder builder() {
        return new TestBuilder();
    }

    public static class TestBuilder {
        private int v1;
        private int v2;
        private int v3;

        TestBuilder() {
        }

        public TestBuilder v1(final int v1) {
            this.v1 = v1;
            return this;
        }

        public TestBuilder v2(final int v2) {
            this.v2 = v2;
            return this;
        }

        public TestBuilder v3(final int v3) {
            this.v3 = v3;
            return this;
        }

        public Test build() {
            return new Test(this.v1, this.v2, this.v3);
        }

        public String toString() {
            return "Test.TestBuilder(v1=" + this.v1 + ", v2=" + this.v2 + ", v3=" + this.v3 + ")";
        }
    }
}

생각했던 것처럼 Lombok은 마술처럼 코드를 작성해줬다. 다만 Builder에서 필수값을 지정하고 싶다면 Lombok에서 사용하는 Builder 메서드를 Custom 한 후 직접 builder() 메서드를 재정의해주면 된다.


    public static TestBuilder builder(String v1) {
        return lombokBuilder().v1(v1);
    }

    @Builder(builderMethodName = "lombokBuilder")
    public Test(String v1, int v2, int v3) {
        this.v1 = v1;
        this.v2 = v2;
        this.v3 = v3;
    }

이렇게 되면 Test.builder("Notnull").v2(2).build()와 같이 필수값을 직접 입력받을 수 있게 된다.

Back to [TIL] 230116