-
[디자인 패턴] 빌더 패턴 (Builder Design Pattern)Computer Science/Design Pattern 2022. 10. 9. 01:47728x90
빌더 패턴 (Builder Pattern)
- GoF 디자인 패턴 중 생성 패턴에 해당
- 빌더 패턴은 복잡한 객체를 생성하는 클래스와 표현하는 클래스를 분리
- 다른 표현이라도 이를 생성할 수 있는 동일한 절차를 제공하는 패턴
주로 클래스에 새로운 객체 생성 시, 객체에 값을 할당하는 방법
1. 생성자 이용
2. Setter 메서드 이용
빌더 패턴이 필요한 경우
- 클래스에 대한 속성 값이 optional 일때
- 클래스 객체의 여러 속성 값 중 하나 null이 되는 경우
- 데이터 입력하는 순서가 달라질 수 있을 때
- 새로운 객체를 만들 때마다 객체 내부 인자를 어떻게 부여해서 생성해야 하는지 모르는 경우 발생
* 기존 클래스 생성자를 이용한 객체 생성 시 명확하게 데이터 입력하는 순서를 알아야 하는 문제점 발생
장점
- 표현을 다양하게 변경 가능
- 생성과 표현 코드를 분리
- 복합 객체를 생성하는 절차를 세밀하게 나눌 수 있음
코드 설명
기존 직접 클래스 생성자를 이용한 객체 생성 방법
클래스 다이어그램 Task.java
import java.util.Date; //일정 관리를 위해 새롭게 생성되는 일정(Task)클래스 public class Task { //Task 클래스의 속성 private final long id; //일정에 대한 unique identifier private String summary = ""; //일정에 대한 요약 private String description = ""; //일정에 대한 상세 설명 private boolean done = false; //일정이 완료되었는지 완료되지 않았는지를 설명하는 변수 private Date dueDate; //해당 Task가 언제인지 기록하는 변수 //Source - Generate Constructor Using Fields (생성자 만들기) //Task class를 외부 클라이언트에서 생성시 생성자 활용 public Task(long id, String summary, String description, boolean done, Date dueDate) { super(); this.id = id; this.summary = summary; this.description = description; this.done = done; this.dueDate = dueDate; } }
Client.java
import java.util.Date; public class Client { public static void main(String[] args) { Task(long id, String summary, String description, boolean done, Date dueDate) //생성자를 통한 객체 생성 //일정을 만들 때, 일정에 대한 고유 id와 summary, description에 대한 정보만 알고 있는 경우 Task t1 = new Task(1000,"TEST","TEST",false,null); //t1 객체 생성 //일정들이 생성될때마다 빈값, null이 들어오는 경우, //객체 생성시 매번 어느 부분이 null인지 매번 체크해야 되는 경우 발생 Task t2 = new Task(1001,"","",false,null); //객체 내부 인자를 어떻게 부여해야하는지 모르는 경우 발생 (입력의 순서가 바뀔 수 있을 때) Task t3 = new Task(false, null, 1002, "",""); } }
문제점
- Task 클래스의 생성자를 이용한 객체 생성 시, 해당 클래스의 속성을 순서대로 기입해야 한다.
- 속성 값 중 null이 존재할 경우 어떤 속성이 null인지 항상 체크해야 한다.
- 내부 인자를 어떻게 부여해야 하는지 모를 경우 오류 발생.
싱글톤 패턴을 이용한 객체 생성
빌더패턴 이용 클래스다이어 그램 Task.java
import java.util.Date; //일정 관리를 위해 새롭게 생성되는 일정(Task)클래스 public class Task { private final long id; //일정에 대한 unique identifier private String summary = ""; //일정에 대한 요약 private String description = ""; //일정에 대한 상세 설명 private boolean done = false; //일정이 완료되었는지 완료되지 않았는지를 설명하는 변수 private Date dueDate; //해당 Task가 언제인지 기록하는 변수 //Source - Generate Constructor Using Fields (생성자 만들기) //Task class를 외부 클라이언트에서 생성시 생성자 활용 public Task(long id, String summary, String description, boolean done, Date dueDate) { super(); this.id = id; this.summary = summary; this.description = description; this.done = done; this.dueDate = dueDate; } //각각의 속성 출력하기 위한 toString 클래스 @Override public String toString() { return "Task [id=" + id + ", summary=" + summary + ", description=" + description + ", done=" + done + ", dueDate=" + dueDate + "]"; } }
TaskBuilder.java
import java.util.Date; public class TaskBuilder { //Task의 객체를 대신 만들어줌 //Task가 가지고 있는 변수(속성) private final long id; //일정에 대한 unique identifier private String summary = ""; //일정에 대한 요약 private String description = ""; //일정에 대한 상세 설명 private boolean done = false; //일정이 완료되었는지 완료되지 않았는지를 설명하는 변수 private Date dueDate; //해당 Task가 언제인지 기록하는 변수 // id값만 처음 인자로 받으면, 나머지는 setter이용해서 설정 //TaskBuilder의 생성자 public TaskBuilder(long id) { this.id = id; } //각 속성에 대한 setter정의. 생성자를 통해 정의된 인자 값 추후 수정을 위함 public void setSummary(String summary) { this.summary = summary; } public void setDescription(String description) { this.description = description; } public void setDone(boolean done) { this.done = done; } public void setDueDate(Date dueDate) { this.dueDate = dueDate; } //TaskBuiler 객체 생성 후 실제 Task 객체 생성해야 함. //TaskBuilder 객체가 보유한 값들을 활용하여 최종적으로 Task 객체를 만드는 메소드 public Task build() { return new Task(id, summary, description, done, dueDate); } }
- Task를 생성할 속성 값들을 setter 메서드를 통해 값을 받아올 수 있다.
- 그 후 build() 메소드를 통해 실제 Task 객체를 생성한다.
각각의 값이 변동될 수 있는 속성, optional 하게 받을 수 있는 속성에 대해 각각 setter를 만들었으므로,
클라이언트는 속성의 순서를 고려할 필요가 없다.
Client.java
import java.util.Date; public class Client { public static void main(String[] args) { //빌더 객체를 통한 객체 생성 TaskBuilder taskBuilder1 = new TaskBuilder(999); taskBuilder1.setSummary("TEST"); taskBuilder1.setDone(false); taskBuilder1.setDescription("example"); //해당값을 알지 못하는 경우, 그냥 set하지 않으면 null로 이미 설정되어있음. //클라이언트는 굳이 모르는값 명시 안해도된다. //최종적으로 앞서 대입한 값에 대해 build()메소드 이용 Task 객체 생성 Task task1 = taskBuilder1.build(); System.out.println(task1); } }
실제 클라이언트는 TaskBuilder의 객체를 생성하고 그 객체에 setter 메소드를 이용해서 변동되는 속성 값들을 순서와 상관없이 추가하고 최종적으로 build() 메소드를 사용하면 실제 Task의 객체가 생성된다.
실행 결과
싱글톤 패턴을 이용하여 Client에서 추가한 속성들을 포함하여 객체가 잘 생성된 것을 확인할 수 있다.
728x90반응형'Computer Science > Design Pattern' 카테고리의 다른 글
[디자인패턴] 8. 커맨드 패턴 (Command Design Pattern) (0) 2022.10.31 [디자인 패턴] 7. 스테이트 패턴 (State Design Pattern) (0) 2022.10.14 [디자인 패턴] 6. 싱글턴 패턴 (Singleton Design Pattern) (2) 2022.10.09 [디자인 패턴] 5. 스트래티지 패턴 (Strategy Design Pattern) (0) 2022.09.25 [디자인 패턴] 4. 디자인 패턴 (0) 2022.09.16