디자인 패턴

[디자인패턴]빌더 패턴

Ash_jisu 2023. 10. 12. 21:31

빌더패턴

  • 집을 생각해보면 각각의 집들은 다른 요소들이 있을 수 있다.(주차장, 창문, 수영장, 정원) 근데 이런 집을 다 따로 만들자니 종류가 너무 많아지고 이거를 파라미터값으로 다 넣어주자니 메서드 하나에 파라미터값이 많아진다.

 

  • 해결법: 빌더 패턴은 복잡한 객체들을 단계별로 생성할 수 있다. 그리고 빌더는 제품이 생성되는 동안 다른 객체들이 제품에 접근 하는 것을 허용하지 않는다.

 

자세한 내용은 아래 실습 예제를 보여주면서 설명하겠다.

 


실습 예제

Builder패턴 적용 이전

  • 객체에 값을 할당하는 방법
    • 생성자 생성
    • Setter 생성
  • Task클래스와 Client 클래스 코드
    Task
import java.util.Date;

public class Task{
	//항상 외부에서 사용못하게 하는 변수는 private!!
	private final long id;
	private String summary = "";
	private String description = "";
	private boolean done = false;
	private Date dueDate;
	
	//생성자 생성
	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;
	}

	//getter and setter
	public String getSummary() {
		return summary;
	}

	public void setSummary(String summary) {
		this.summary = summary;
	}

	public String getDescription() {
		return description;
	}

	public void setDescription(String description) {
		this.description = description;
	}

	public boolean isDone() {
		return done;
	}

	public void setDone(boolean done) {
		this.done = done;
	}

	public Date getDueDate() {
		return dueDate;
	}

	public void setDueDate(Date dueDate) {
		this.dueDate = dueDate;
	}

	public long getId() {
		return id;
	}
}

               Client

public class Client {

	public static void main(String[] args) {
		Task t1 = new Task(1000, "TEST", "TEST", false, null);
	}
}

 

위의 예시를 보면 빌더 패턴이 필요한 이유를 알 수 있다

  1. 파라미터 값이 너무 많다(5개) -> 줄여야할때
  2. 클래스 속성 값이 optional일때
  3. 데이터를 입력하는 순서가 달라질 수 있을때

 

Builder패턴 적용 이후

  • Task클래스, TaskBuilder 클래스 생성
    • 위에 잘못된 예시 Task코드를 TaskBuilder에 넣어준다
    • 이후 TaskBuilder클래스 안에 TaskBuilder 객체가 보유한 값들을 활용하여 최종적으로 Task객체를 만드는 메서드를 만들어준다
  • TaskBuilder, Task, Client 클래스 생성
    TaskBuilder
import java.util.Date;

public class TaskBuilder{
	//항상 외부에서 사용못하게 하는 변수는 private!!
	private final long id;
	private String summary = "";
	private String description = "";
	private boolean done = false;
	private Date dueDate;
	
	//생성자 생성
	public TaskBuilder(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;
	}

	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;
	}

	//Task생성
	public Task build() {
		return new Task(id, summary, description, done, dueDate);
	}
}

Task     

밑에 Task를 객체를 프린트할때 값이 나오게끔 toString 메서드를 추가해준다

import java.util.Date;

public class Task{
	//항상 외부에서 사용못하게 하는 변수는 private!!
	private final long id;
	private String summary = "";
	private String description = "";
	private boolean done = false;
	private Date dueDate;
	
	//생성자 생성
	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;
	}

	//getter and setter
	public String getSummary() {
		return summary;
	}

	public void setSummary(String summary) {
		this.summary = summary;
	}

	public String getDescription() {
		return description;
	}

	public void setDescription(String description) {
		this.description = description;
	}

	public boolean isDone() {
		return done;
	}

	public void setDone(boolean done) {
		this.done = done;
	}

	public Date getDueDate() {
		return dueDate;
	}

	public void setDueDate(Date dueDate) {
		this.dueDate = dueDate;
	}

	public long getId() {
		return id;
	}

	@Override
	public String toString() {
		return "Task [id=" + id + ", summary=" + summary + ", description=" + description + ", done=" + done
				+ ", dueDate=" + dueDate + "]";
	}
	
}

 

 

Client

public class Client {

	public static void main(String[] args) {
			  //빌더 패턴 적용 후
			  TaskBuilder taskBuilder1 = new TaskBuilder(999);
			  taskBuilder1.setSummary("test");
			  
			  //TaskBuilder을 통해 만든 객체로 Task생성
			  Task t1 = taskBuilder1.build();
			  System.out.print(t1);
	}
}

 

    출력 결과

 

 


Builder 패턴의 장점과 이미지화

장점

  • 이제는 더이상 Task를 만들때 파라미터 순서를 생각 안해도된다. 필수적으로 넣어아하는 id만 넣으면 됨
  • setter메서드를 통해 값 하나하나 필요한 것만 지정가능(Null일일히 넣을필요도 없음)

 

이미지화

 

 


참고

https://refactoring.guru/ko/design-patterns/builder