티스토리 뷰
1. 점층적 생성자 패턴( telescoping constructor pattern)
가장 일반적인 패턴이다.
간단히 요약하면 매개변수를 1개 받는 생성자, 2개 받는 생성자 ~ (반복) 결국에는 전부 다 받는 생성자까지 모두 만들어 주는 방식이다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | public class Person { private final String name; private final int age; private final String address; // 1개의 인자를 받는 생성자 (필수인자) public Person(String name) { this(name, 0); } // 2개의 인자를 받는 생성자 public Person(String name, int age) { this(name, age, null); } // 3개의 인자를 모두 받는 생성자 public Person(String name, int age, String address) { this.name = name; this.age = age; this.address = address; } } | cs |
(무식한 방법으로 모든 생성자에 대해 구현하기 보다는, 위와같이 this 를 활용하여 코드를 비교적 간단하게 짤 수 있다.)
소스를 보면 이해가 되겠지만 점층적 생성자 패턴의 단점은 다음과 같다.
생성자가 다른 생성자를 계속해서 호출하는 구조이기 때문에, 필드가 추가되면 코드의 수정도 그만큼 복잡하다. (가독성 역시 떨어진다)
또한 클라이언트 측에서 인자를 많이 받는 생성자를 호출하는 모습은 다음과 같을 것이다.
1 | ManyClass manyClass = new ManyClass("Y", 100, 20, 0, "Y", "N", 5, 60); | cs |
생성자 소스를 직접 보지 않는 한, 위의 인자들이 어떤 값을 의미하는지 이해하기 어렵다... 또 굳이 값을 넣을 필요가 없는 필드에도 값을 넣어주어야 한다.
2. 자바빈 패턴(JavaBeans Pattern)
간단하다. 인자가 없는 생성자를 호출하여 객체를 먼저 생성한 다음, setter 를 통해 해당 객체의 필드를 채우는 방식이다.
1 2 3 4 5 | Person person = new Person(); person.setName("developer"); person.setAge(29); person.setAddress("Pangyo"); | cs |
위에서 본 점층적 생성자 패턴에서의 문제점들은 해결된 모습이다.
객체 생성이 간단하고, 필드에 값을 적용하는 것도 간단하다.
또한 setter 메소드 명을 통해 어떤 필드에 어떤 값을 적용하는지 명확하다. 결과적으로 가독성 역시 올라갔다.
하지만 자바빈 패턴에는 역시 다음과 같은 단점이 존재한다.
점층적 생성자 패턴과는 다르게 1회의 생성자 호출로 객체를 완전히 생성하지 못한다.
즉, setter 메소드를 통해 생성 시점 이후에도 값이 변할 수 있기 때문에 객체의 일관성(consistency)이 깨지게 된다.
마찬가지 이유로 변경 불가능(immutable) 클래스를 만들 수가 없다.
3. 빌더 패턴(Builder Pattern)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | public class Person { private final String name; private final int age; private final String address; public static class Builder { // 필수 인자 private final String name; // 선택 인자 (default 값 셋팅) private int age = 0; private String address = ""; public Builder(String name) { this.name = name; } public Builder age(int val) { age = val; return this; } public Builder address(String val) { address= val; return this; } public Person build() { return new Person(this); } } public Person(Builder builder) { name = builder.name; age = builder.age; address = builder.address; } } | cs |
빌더 패턴을 처음 접하는 사람이라면 이 복잡한 소스가 도대체 왜 앞선 패턴들보다 좋은지 이해하기 힘들 수 있으나,
실제 객체를 생성하는 코드를 확인해보자.
1 2 3 4 | Person person = new Person().builder("developer") .age(29) .address("Pangyo") .build(); | cs |
마치 setter 를 사용하는 것 처럼 필드에 값을 적용하는 부분이 보기 명확하다. 따라서 가독성이 우수하다.
(위와 같은 코드를 체이닝이라고 한다.)
또한 최종적으로 build() 메소드를 호출하면서 객체가 생성되기 때문에 자바빈 패턴에서 나타났던 단점도 없다.
하지만 빌더 패턴 역시 단점이 존재 한다.
객체가 생성됨에 있어서 빌더 역시 함께 생성이 되어야 한다. 성능상의 이슈가 예민한 시스템이라면 고려해야 한다.
그리고 위와같이 다른 패턴들에 비해 코드가 다소 복잡하기 때문에, 인자가 많은 클래스에서 적용하는 것이 더욱 효과적이다.
※ 마지막으로 팁! (Tip)
보통의 경우 Eclipse(STS)나 IntelliJ 등의 IDE 에서 자바 개발을 한다.
해당 IDE 에서는 Lombok 라이브러리를 활용할 수 있다.
Lombok 에서 제공하는 @Builder 어노테이션을 활용하면 위의 소스를 아래와 같이 간편하게 작성할 수 있다.
1 2 3 4 5 6 7 8 | @Builder public class Person { private final String name; private final int age; private final String address; } | cs |
'개발 > Java' 카테고리의 다른 글
[스프링부트 기초3] Postman과 H2 를 이용한 CRUD API 확인 (2) | 2019.03.10 |
---|---|
[스프링부트 기초2] JPA를 활용하여 CRUD API 만들기 (1) | 2019.03.03 |
[스프링부트 기초1] 스프링부트(Spring Boot) 시작하기 (IntelliJ) (4) | 2019.02.10 |
- Total
- Today
- Yesterday
- 프로미스
- jest
- KCD
- 이벤트루프
- nuxtjs
- 자바스크립트
- event loop
- CommonJs
- 테스트코드
- 스프링부트
- javascript engine
- vue.js
- KCD2019
- 모듈시스템
- 근본설
- 인텔리제이
- 빌더패턴
- Builder
- javascript
- await
- vuejs
- promise
- nuxt
- vue
- es6
- 근본
- intellij
- 야누자이
- 자바스크립트 엔진
- springboot
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |