728x90
Java 객체 생성 방법
1. 점층적 생성자 패턴
점층적 생성자 패턴을 만드는 방법은 다음과 같다.
- 필수 인자를 받는 필수 생성자 를 하나 만든다.
- 1개의 선택적 인자를 받는 생성자를 추가한다.
- 2개의 선택적 인자를 받는 생성자를 추가한다.
- ...
- 모든 선택적 인자를 받는 생성자를 추가한다.
// 점층적 생성자 패턴 코드의 예
public class Member {
private final String name; // 필수 인자
private final String age; // 선택적 인자
private final String location; // 선택적 인자
// 필수 생성자
public Member(String name) {
this(name, "나이 비공개", "지역 비공개");
}
// 1개의 선택적 인자를 받는 생성자
public Member(String name, String age) {
this(name, age, "지역 비공개");
}
// 모든 선택적 인자를 다 받는 생성자
public Member(String name, String age, String location) {
this.name = name;
this.age = age;
this.location = location;
}
}
-
장점
new Member("홍길동", "나이 비공개", "지역 비공개")
와 같은 호출이 빈번하게 일어난다면,new Member("홍길동")
으로 대체할 수 있다. -
단점
- 다른 생성자를 호출하는 생성자가 많으므로, 인자가 추가되는 일이 발생하면 코드를 수정하기 어렵다.
- 코드 가독성이 떨어진다. 특히, 인자 수가 많을 때 호출 코드만 봐서는 의미를 알기 어렵다.
- 설정할 필요가 없는 필드에도 인자를 전달해야 하는 경우가 생긴다.
2. 자바빈 패턴
점층적 생성자 패턴의 대안으로 자바빈 패턴(JavaBeans Pattern)이 있다.
public class CafeMenu {
private int coffee = 1; // 필수 인자
private int beverage = 1; // 필수 인자
private int dessert = 0; // 선택적 인자
private int bakery = 0; // 선택적 인자
private int drinks = 0; // 선택적 인자
public CafeMenu() {}
// setter 메서드 정의
public void setCoffee(int coffee) {
this.coffee = coffee;
}
public void setBeverage(int beverage) {
this.beverage = beverage;
}
public void setDessert(int dessert) {
this.dessert = dessert;
}
public void setBakery(int bakery) {
this.bakery = bakery;
}
public void setDrinks(int drinks) {
this.drinks = drinks;
}
}
자바빈 패턴은 setter 메서드를 사용해서 인자에 말그대로 set 해주는 방법이다. CafeMenu 객체를 만들고 싶다면
public class GetCafeMenu {
public static void main(String[] args) {
CafeMenu starbucks = new CafeMenu();
starbucks.setCoffee(10);
starbucks.setBeverage(30);
starbucks.setDessert(10);
starbucks.setBakery(20);
starbucks.setDrinks(5);
}
}
위와 같이 setter 메서드를 통해서 객체를 생성할 수 있다.
-
장점
- 각 인자의 의미를 파악하기가 쉽다.
- 복잡하게 여러 개의 생성자를 만들지 않아도 된다.
-
단점
- 1회의 호출로 객체 생성이 끝나지 않기 때문에 객체 일관성(consistency)이 깨진다.
- setter 메서드가 있으므로 변경 불가능(immutable) 클래스를 만들 수가 없다.
- 스레드 안정성을 확보하려면 점층적 생성자 패턴보다 많은 일을 해야 한다.
3. 빌더 패턴
빌더 패턴(Builder Pattern)은 점층적 생성자 패턴의 안정성과 자바진 패턴의 가독성을 결합한 패턴이다.
public class CafeMenu {
private final int coffee; // 필수 인자
private final int beverage; // 필수 인자
private final int dessert; // 선택적 인자
private final int bakery; // 선택적 인자
private final int drinks; // 선택적 인자
public static class Builder {
private final int coffee; // 필수 인자
private final int beverage; // 필수 인자
private int dessert; // 선택적 인자
private int bakery; // 선택적 인자
private int drinks; // 선택적 인자
// 필수 인자 생성자
public Builder(int coffee, int beverage) {
this.coffee = coffee;
this.beverage = beverage;
}
// 선택적 인자는 Builder 타입의 함수로 만든다.
public Builder dessert(int val) {
dessert = val;
return this;
}
public Builder bakery(int val) {
bakery = val;
return this;
}
public Builder drinks(int val) {
drinks = val;
return this;
}
// CafeMenu 타입으로 만들기 함수
public CafeMenu build() {
return new CafeMenu(this);
}
}
private CafeMenu(Builder builder) {
coffee = builder.coffee;
beverage = builder.beverage;
dessert = builder.dessert;
bakery = builder.bakery;
drinks = builder.drinks;
}
}
- CafeMenu 객체의 각 인자(coffee, beverage, dessert, bakery, drinks)가 final로 선언되어있으므로 변경 불가능하다. (immutable)
- 모든 인자의 기본값(default value)이 한 곳에 모여있다.
- Builder 객체 내에서 필수 인자는 final로 선언함으로써 필수적으로 생성자를 통해 생성한다.
- Builder 객체 내에서 선택 인자를 기본값으로 초기화하고 Builder형으로 자기 자신을 반환한다.
- Builder 객체 내의 build 메서드로 빌더 객체 자신을 CafeMenu 형으로 반환한다.
빌더 패턴을 이용한 객체 생성은 다음과 같이 할 수 있다.
public class getCafeMenu {
public static void main(String[] args) {
CafeMenu.Builder builder = new CafeMenu.Builder(20, 10);
builder.drinks(5);
CafeMenu coffeeBean = builder.build();
// 한 줄로 이어서 작성 가능하다.
CafeMenu starbucks = new CafeMenu.Builder(30, 20).bakery(10).dessert(5).drinks(10).build();
}
}
-
장점
- 각 인자가 어떤 의미인지 알기 쉽다.
- setter 메서드가 없으므로 변경 불가능 객체를 만들 수 있다.
- 한 번에 객체를 생성하므로 객체 일관성이 깨지지 않는다.
- build() 함수가 잘못된 값이 입력되었는지 검증하게 할 수도 있다.
-
단점
- 빌더 객체를 생성해야 하기 때문에 코드가 길어질 수 있다.
- 빌더 객체 때문에 오버헤드가 일어날 가능성은 적지만, 성능이 중요한 상황에서는 잘 고려해서 사용해야 한다.
빌더 패턴은 인자가 많은 생성자 나 정적 팩토리가 필요한 클래스 설계할 때 , 특히 대부분의 인자가 선택적 인자인 상황 에 유용하다.
Lombok @Builder
빌더 패턴은 Lombok의 @Builder
어노테이션으로 쉽게 사용할 수 있다.
@Builder
public class NutritionFacts {
private final int servingSize;
private final int servings;
private final int calories;
private final int fat;
private final int sodium;
private final int carbohydrate;
}
객체 생성은 다음과 같이 할 수 있다.
public class GetNutritionFacts {
public static void main(String[] args) {
NutritionFacts.NutritionFactsBuilder builder = NutritionFacts.builder();
builder.calories(230);
builder.fat(10);
NutritionFacts facts = builder.build();
// 또는
NutritionFacts facts = NutritionFacts.builder().calories(230).fat(10).build();
}
}
Reference
728x90
'Etc > 2020' 카테고리의 다른 글
[Web] 잠드는 시간 추천해주는 사이트 만들기! (0) | 2020.08.03 |
---|---|
[Eclipse] SVN Compare 시 한글 깨짐 현상 해결 (0) | 2020.06.22 |
[기초] MVC 패턴 (0) | 2020.06.08 |
[Java] 객체 지향 프로그래밍(OOP, Object Oriented Programming) (0) | 2020.06.08 |
[HTML] HTML5 기본 문법 정리 (0) | 2020.06.04 |