방법 1 점층적 생성자 패턴
public class Member {
private String name; // 필수
private int age; // 필수
private String address; // 선택
private String phone; // 선택
private String email; // 선택
// 필수 매개변수를 가지는 생성자
public Member(String name, int age) {
this(name, age, null, null, null);
}
// 선택 매개변수 address가 추가된 생성자
public Member(String name, int age, String address) {
this(name, age, address, null, null);
}
// 선택 매개변수 phone이 추가된 생성자
public Member(String name, int age, String address, String phone) {
this(name, age, address, phone, null);
}
// 모든 매개변수를 가지는 생성자
public Member(String name, int age, String address, String phone, String email) {
this.name = name;
this.age = age;
this.address = address;
this.phone = phone;
this.email = email;
}
}
//참고 : https://wildeveloperetrain.tistory.com/29
생성자를 여러개 선언하는 방법으로 수정이 번거롭고 가독성도 나쁘다.
방법 2 자바 빈즈 패턴
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
public void setAddress(String address) {
this.address = address;
}
public void setPhone(String phone) {
this.phone = phone;
}
public void setEmail(String email) {
this.email = email;
}
//참고 : https://wildeveloperetrain.tistory.com/29
Member member = new Member();
member.setName("jan");
member.setAge(99);
member.setAddress("KOR");
member.setPhone("01012345678");
//참고 : https://wildeveloperetrain.tistory.com/29
객체가 완전히 설정되기 전에는 일관성이 무너진다.
불변으로 생성이 불가하다.
방법 3 빌더 패턴
위의 두가지 방법을 결합하여 장점만을 지닌 패턴
필수적인 파라미터들은 생성자를 사용하여 입력 받는다. → 생성자를 이용한 장점
추가적인 파라미터들은 자바 빈즈 패턴(set 메소드 활용)을 사용해서 입력을 받는다. → 자바 빈즈의 장점
set 메소드들의 리턴 타입을 빌더 자기 자신으로 설정하여 fluent API
, 메서드 연쇄
할 수 있도록 구현한다.
빌더 심화 (게층적으로 설계된 클래스와 빌더)
이해가 되지 않는다면 출처 링크에 들어가거나 책을 참조하자
import java.util.*;
public abstract class Pizza{
public enum Topping { HAM, MUSHROOM, ONION, PEPPER, SAUSAGE }
final Set<Topping> toppings;
abstract static class Builder<T extends Builder<T>> {
EnumSet<Topping> toppings = EnumSet.noneOf(Topping.class);
// 하위 클래스 에서 공통으로 사용할 토핑
public T addTopping(Topping topping) {
toppings.add(Objects.requireNonNull(topping));
return self();
}
// Pizza 를 상속받은 클래스 ( NyPizza , Calzone ) return
// 메서드를 구현할 때 NyPizza 와 Calzome의 생성자를 호출하게 된다.
// new NyPizza(this) , new Calzone(this);
abstract Pizza build();
// 하위 클래스는 이 메서드를 재정의하고 this를 반환하도록 해야 한다.
protected abstract T self();
}
// 저장된 토핑이 build()를 호출할 때 각각 생성자에서 super(builer)를 호출하고
// super는 Pizza의 생성자 이므로 아래의 Pizza가 호출 되면서 토핑을 clone()해서
// 저장한다.
Pizza(Builder<?> builder) {
toppings = builder.toppings.clone();
}
// 실제 토핑값을 찍어보기 위한 toString() 재정의
@Override
public String toString() {
Iterator iterator = toppings.iterator();
String returnStr = "";
while(iterator.hasNext()) {
returnStr += iterator.next() + ", ";
}
return returnStr;
}
}
import java.util.Objects;
public class NyPizza extends Pizza {
public enum Size { SMALL, MEDIUM, LARGE }
private final Size size;
public static class Builder extends Pizza.Builder<Builder> {
private final Size size;
// NyPizza 는 size를 받는 생성자만 존재함.
public Builder(Size size) {
super();
this.size = Objects.requireNonNull(size);
}
@Override public NyPizza build() {
return new NyPizza(this);
}
@Override protected Builder self() { return this; }
}
private NyPizza(Builder builder) {
super(builder);
size = builder.size;
}
}
출처 : effective java
출처: https://debaeloper.tistory.com/35 [이해시키지 못하면, 이해한게 아니다.:티스토리]
'programming > java' 카테고리의 다른 글
Item4. 인스턴스화를 막으려거든 pricate 생성자를 사용하라 (0) | 2023.03.23 |
---|---|
Item 55. 옵셔널 반환은 신중히 하라 (0) | 2023.03.17 |
Item 54. null이 아닌, 빈 컬렉션이나 배열을 반환하라 (0) | 2023.03.17 |
Item 3. private 생성자나 열거 타입으로 싱글턴임을 보증하라 (0) | 2023.03.16 |
Item1. 생성자 대신 정적 팩터리 메서드를 고려하라. (0) | 2023.03.13 |