먼저 , 학생이라는 객체를 생성하는 코드가 있고 , 아래와 같은 생성자 정의해두었다고 가정한다.
public Student(long id,String name,String major,int age,String address){
this.id=id;
this.name=name;
this.major=major;
this.age = age;
this.address = address;
}
여기서 클라이언트 입장에서 인스턴스를 생성한다고 생각한다.
Student student = new Student(123,'jsh','py',25,'pankyo');
위와 같이 생성할 수 있을것이다.
그렇다면 아래와 같은 경우는?
Student student = new Student(123,'lsh',null,0,null);
이럴 경우 생성자 오버로딩을 통해 문제를 해결할 수 있을것이다. [ 점층적 생성자 패턴 ]
...
public Student(long id,String name){
this.id=id
this.name=name
}
public Student(long id,String name,String major){
this.id=id
this.name=name
this.major=major
}
public Student(long id,String name,String major, String address){
this.id=id
this.name=name
this.major=major
this.address=address
}
...
그러나 생성자 오버로딩을 사용하면 위와 같이 코드가 길어진다.
Student student = new Student(123,'lsh',null,0,null)
또한 특정 파라미터가 어떤 값을 나타내는지 알기 힘들다.
그렇다면 setter 메서드를 사용하면? [ 자바 빈 패턴 ]
Student student = new Student();
student.setId(1234);
student.setName('lsh');
student.setAge(25);
student.setMajor('sample');
student.setAddress('pankyo');
// set메서드를 이용하여 코드를 한 줄씩 입력하여 계속 변경되며 , 한 번에 만들어지지 않음
먼저 , 함수 호출 1회로 객체 생성을 끝낼수 없다 또한 객체 일관성이 일시적으로 깨질수 없으며 불변(immutable)객체를 생성할수 없다.
따라서 위의 두가지 패턴에서 장점만 뽑아온 빌더패턴을 사용한다.
빌더 패턴(Builder Pattern)
빌더 패턴의 적용 방식은 클라이언트 코드에서 필요한 객체를 직접 생성하는 대신
1. 필수 인자들을 전달하여 빌더 객체를 만든 뒤,
2. 빌더 객체에 정의된 설정 메서드들을 호출하여 인스턴스를 생성한다.
빌더 패턴의 장점
1.인스턴스를 생성하는데 있어 필수적인 인자와 선택적인 인자 구별 가능
2.선택적인 인자의 경우 , 가독성이 좋은 코드로 인자를 넘길수 있다.
3.객체 일관성이 깨지지 않는다.
public interface Buildable<T> {
T build();
}
먼저 , interface를 하나 만들어 다른 builder에도 적용할 수 있게 한다.
public class Student{
private long id;
private String name;
private String major;
private int age;
private String address;
public Student() {} // Student 기본 생성자
public static class Builder implements Buildable {
private final long id; //final : 값을 한번 할당하면 수정 불가능
private final String name;
private String major="";
private int age=0;
private String address="";
public Builder(long id, String name){
this.id = id;
this.name = name;
} // Bulider의 기본 생성자라 볼 수있음
public Builder major(String major){
this.major = major;
return this;
}
public Builder age(int age){
this.age = age;
return this;
}
public Builder address(String address){
this.address = address;
return this;
}
public Student build(){
return new Student(this);
} // 최종적으로 빌드
}
private Student(Builder builder){
this.id = builder.id;
this.name = builder.name;
this.major = builder.major;
this.age = builder.age;
this.address = builder.address;
}
}
Student 클래스안에 Builder 라는 정적 멤버 클래스를 만든 후 interface를 implements한다.
최종적으로 build() 메서드를 통해 인스턴스를 생성한다.
Student 클래스 필드 중 id와 name을 필수 인자를 선택하여 final 설정을 한 후,
나머지 선택적 인자들은 Builder를 return 하게 한다.
이제 , 클라이언트 코드에서
Student s1 = new Student.Builder(1231,'lsh')
.major("program")
.age(25)
.address('seoul')
.build();
여러 개의 파라미터를 전달하여도 어떤 값이 어떤 의미인지 파악할 수 있고, 필수 인자와 선택적 인자도 구별 가능하다.
'지식 저장소' 카테고리의 다른 글
같은 값 기준 정렬 후 페이징 시 목록 꼬임 문제 (0) | 2023.01.10 |
---|---|
Replication(복제) (0) | 2022.09.08 |
Cannot add or update a child row 에러 (0) | 2022.01.19 |
REST방식 , JSON , AJAX 의미 (0) | 2021.12.28 |
javascript 사용 시 jQuery 미 호출시 오류 (0) | 2021.12.27 |