(디자인 패턴)빌더 패턴 (Builder Pattern)

Builder
홍윤's avatar
Aug 14, 2024
(디자인 패턴)빌더 패턴 (Builder Pattern)
💡
빌더 패턴(Builder Pattern)은 객체 지향 설계에서 많이 사용되는 디자인 패턴 중 하나로, 특히 복잡한 객체를 생성할 때 유용합니다. 이 패턴은 객체의 생성과정을 단순화하고, 객체 생성 중 발생할 수 있는 불필요한 복잡성을 줄이는 데 목적이 있습니다.
 

빌더 패턴의 주요 개념

  1. 복잡한 객체 생성:
      • 빌더 패턴은 특히 여러 매개변수가 필요하거나, 생성 과정이 복잡한 객체를 만들 때 유용합니다. 예를 들어, 특정 객체를 생성하려면 여러 가지 설정이 필요하고, 이러한 설정은 순서에 따라 달라질 수 있습니다. 이런 경우 빌더 패턴을 사용하면 객체를 보다 유연하고 단계적으로 생성할 수 있습니다.
  1. 불변성 유지:
      • 빌더 패턴은 불변 객체(immutable object)를 만들 때 자주 사용됩니다. 객체가 한 번 생성되면 변경되지 않도록 하고 싶을 때, 빌더 패턴을 통해 객체의 모든 속성을 설정한 후 한 번에 생성합니다.
  1. 가독성 향상:
      • 빌더 패턴은 코드의 가독성을 높입니다. 많은 매개변수를 가진 생성자나 메서드 호출을 줄이고, 메서드 체이닝(method chaining)을 통해 더 직관적인 객체 생성을 가능하게 합니다.

빌더 패턴의 구조

  1. Builder:
      • 객체를 생성하는 데 필요한 메서드들을 포함한 클래스입니다. 일반적으로, 각 메서드는 객체의 특정 속성을 설정하고, Builder 객체 자체를 반환하여 메서드 체이닝을 가능하게 합니다.
  1. Product:
      • 빌더 패턴을 통해 생성될 실제 객체입니다. 이 객체는 Builder를 통해 완성된 후 반환됩니다.
  1. Director (선택 사항):
      • 객체 생성 과정을 정의하는 클래스입니다. 복잡한 생성 과정을 여러 단계로 나누어 설정할 수 있습니다. 그러나 단순한 빌더 패턴에서는 Director가 생략되기도 합니다.
 

빌더 패턴의 장점

  1. 유연성:
      • 객체의 속성을 선택적으로 설정할 수 있으며, 복잡한 객체를 단계적으로 생성할 수 있습니다.
  1. 가독성:
      • 메서드 체이닝을 통해 가독성을 높이고, 객체 생성 과정이 더 명확해집니다.
  1. 유지보수성:
      • 빌더 패턴을 사용하면 코드 수정 시 객체 생성 로직의 변화가 최소화됩니다. 새로운 속성을 추가하거나 변경할 때, 기존 코드를 크게 수정하지 않고도 대응할 수 있습니다.
       

빌더 패턴의 단점

  1. 코드 양 증가:
      • 빌더 클래스와 관련 메서드들을 추가로 작성해야 하므로, 단순한 객체를 생성할 때는 오히려 코드가 길어질 수 있습니다.
  1. 복잡성 증가:
      • 매우 간단한 객체를 생성할 때는 빌더 패턴이 오히려 불필요하게 복잡할 수 있습니다.
빌더 패턴은 객체의 생성이 복잡하거나 유연성이 요구될 때 매우 유용하며, 특히 객체의 불변성을 유지하고 싶은 경우 많이 사용됩니다.

1. 빌더 패턴 연습 예제 및 해설

App
package ex09; public class App { public static void main(String[] args) { //builder (순서 상관없이 가독성이 좋아진다.) //생성자 단점 // 1. 순서를 기억 // 2. ex)아이디를 안 넣고 싶고 eamil,age만 넣고 싶으면 따로 email.age 를 만들어야 한다. // 데이터 덩어리들을 만들때 기본변수를 쓰지 않는게 좋다 // Person t1 = Person.builder().id(1).name("홍길동").age(50).email("abc@naver.com"); //Overroding 할 필요가 없다. Person p1 = Person.builder().name("홍길동").email("ssar@nate.com"); System.out.println(p1.getAge()); } }
  • 빌더 패턴을 사용하여 ‘Person’ 객체를 생성하고 있습니다. 이는 생성자나 setter 메서드를 사용 하는 것 보다 더 가독성이 좋고 유연한 객체 생성 방법이다.
  • 생성자 사용의 단점을 극복하며 객체의 필드를 순서와 상관없이, 필요한 것 만 선택적으로 설정 할 수 있다.
  • ‘Person’ 객체의 ‘age’ 필드는 설정되지 않았기 때문에 ‘getAge()’ 메서드는 기본값을 반환할 가능 성이 큽니다.

Person
package ex09; public class Person { // 클래스 자료형 데이터를 만들었다고 생각! 일반적으로 VO // null을 넣을 수 있는게 좋다. 그래서 int변수는 Integer 넣는게 좋다. private Integer id; private String name; private Integer age; private String email; private Person(){ } public static Person builder(){ return new Person(); } //자기자신을 다시 리턴을 한다. this를 자기자신을 가르킨다. public Person id(Integer id){ this.id = id; return this; } public Person name(String name){ this.name = name; return this; } public Person age(Integer age){ this.age=age; return this; } public Person email(String email){ this.email = email; return this; } public Integer getId() { return id; } public String getName() { return name; } public Integer getAge() { return age; } public String getEmail() { return email; } }
  • ‘Person’ 클래스는 빌더 패턴을 사용하여 객체를 생성하는 방법을 구현했다.
  • ‘builder()’ 메소드로 객체를 생성을 시작하며, 각 필드를 설정하는 메소드들이 체이닝 방식으로 호출하고 있다.
💡
체이닝 방식(Method Chaining)은 객체의 메서드들이 자기 자신(’this’)을 반환함으로써, 여러 메서드를 연속적으로 호출할 수 있게 하는 프로그래밍 기법입니다. 이를 통해 코드가 간결하고 가독성이 좋아지며, 객체의 상태를 유연하게 설정할 수 있습니다. 예를 들어, ‘Person.builder().name(”홍길동”).email(”abc@naver.com”)’ 처럼 한 줄로 여러 속성을 설정할 수 있습니다.
장점:
  • 코드가 간결하고 읽기 쉬움
  • 객체 생성 시 유연성 제공
단점:
  • 디버깅과 예외 처리 어려움
  • 중간 상태 확인이 복잡할 수 있음
 
  • 생성자 ‘private’ 으로 선언되어 외부에서 직접 객체 생성을 방지하고, 필드 설정 메소드들은 ‘this’ 를 반환하여 가독성 높은 객체 생성 코드를 작성 할 수 있다.
Share article

Uni