[Java] 빌더 패턴을 써보자!

Bobby·2021년 10월 13일
0

즐거운 개발일지

목록 보기
12/22
post-thumbnail

다음과 같은 멤버변수를 가진 객체가 있다.

public class Member {

    private final String email;	     
    private final String password;   
    private final String name;       
    private final String address;    
    private final String phone;      
    
}

인스턴스를 생성하고 값을 초기화 하려면 어떤 방법이 있을까?

  1. 생성자를 사용
  2. setter 메소드 사용
  3. 빌더 사용
... etc

1. 생성자 사용

  • 생성자를 이용해 생성과 초기화를 한다.
  • 생성과 동시에 초기화를 하므로 final 사용 할 수 있다.
public class Member {

    private final String email;
    private final String password;
    private final String name;
    private final String address;
    private final String phone;

    public Member(String email, String password, String name, String address, String phone) {
        this.email = email;
        this.password = password;
        this.name = name;
        this.address = address;
        this.phone = phone;
    }

    public Member(String email, String password, String name) {
        this(email, password, name, null, null);
    }

    public Member(String email, String password) {
        this(email, password, null, null, null);
    }
    
    ...
    
    // getter, toString
    
}

테스트

  • 생성자 생성은 코드가 간결하다.
public class Test {
    public static void main(String[] args) {

        Member member1 = new Member("email@naver.com", "1234", "kim");
        Member member2 = new Member("email@naver.com", "1234", "kim", "seoul", "01012341234");

        System.out.println("member1 = " + member1);
        System.out.println("member2 = " + member2);
    }
}

단점

  • 멤버변수가 늘어날 경우 생성자의 매개변수가 길어진다.
  • 필수 값과 선택 값에 따라서 다양한 생성자가 필요하다.
  • 매개변수의 순서가 중요하고 각각이 무엇을 의미하는지 직관적으로 알기 어렵다.

2. setter 메소드 사용

  • 객체를 생성하고 setter 메소드를 호출하여 값을 초기화 한다.
  • 원하는 값을 지정하여 초기화 할 수 있다.
  • 메소드 명으로 어떤 변수에 값이 초기화 되는지 직관적으로 알기 쉽다.
private String email;
    private String password;
    private String name;
    private String address;
    private String phone;

    public void setEmail(String email) {
        this.email = email;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }
    
    ...
    
    // getter , toString
    
}

테스트

  • 어떤 값이 초기화 되는지 직관적으로 알 수 있다.
public class Test {

    public static void main(String[] args) {

        Member member = new Member();
        member.setEmail("email@naver.com");
        member.setPassword("1234");
        member.setName("kim");

        System.out.println("member = " + member);
    }
}

단점

  • 객체를 생성하고 나서 여러 메소드를 호출해야 한다.
  • final을 사용할 수 없다.
  • 객체를 생성하고 초기화한 이후에도 값이 변경 될 수 있다.

3. 빌더 패턴 사용

  • Member 객체를 만드는 MemberBuilder 클래스를 만든다.
    여기서는 내부 클래스로 만들었다.
  • 빌더클래스의 setter메소드들은 각 값을 받아 각 멤버변수에 담고 자신을 리턴한다.
  • 따라서 연쇄적으로 메소드들을 호출 할 수 있다.
  • 빌더 클래스에서 값을 초기화 한 후 최종적으로 Member 의 생성자를 호출한다.
  • final 사용 가능.
public class Member {

    private final String email;
    private final String password;
    private final String name;
    private final String address;
    private final String phone;

    // 객체 생성
    public Member(String id, String password, String name, String address, String phone) {
        this.email = id;
        this.password = password;
        this.name = name;
        this.address = address;
        this.phone = phone;
    }

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

    public static class MemberBuilder {
        private String email;
        private String password;
        private String name;
        private String address;
        private String phone;

        // 빌더 클래스는 외부 생성 불가 
        private MemberBuilder() {
        }

        public MemberBuilder email(String email) {
            this.email = email;
            return this;
        }
        public MemberBuilder password(String password) {
            this.password = password;
            return this;
        }
        public MemberBuilder name(String name) {
            this.name = name;
            return this;
        }
        public MemberBuilder address(String address) {
            this.address = address;
            return this;
        }
        public MemberBuilder phone(String phone) {
            this.phone = phone;
            return this;
        }
        public Member build() {
            return new Member(email, password, name, address, phone);
        }
    }

    ...
    
    // getter, toString
}

테스트

  • 어떤 값이 초기화 되는지 직관적으로 알 수 있다.
public class Test {

    public static void main(String[] args) {

        Member member = Member.builder()
                .email("email@naver.com")
                .name("kim")
                .password("1234")
                .build();

        System.out.println("member = " + member);
    }
}

단점

  • 빌더 클래스를 생성해야한다.

코드

profile
물흐르듯 개발하다 대박나기

0개의 댓글