본문 바로가기
Spring Boot

230210 Spring Boot Builder패턴(디자인패턴)

Builder패턴(디자인패턴)

빌더 패턴을 사용하면 어느 필드에 어떤 값을 채워야 할지 명확하게 알 수 있다.
스프링부트에서 자주 사용.

클래스 안에 내부클래스를 생성하고, 값을 저장함.
setter메서드와 public생성자가 없어서 처음 생성될 때 값을 지정하고 값을 변경하지 못하게 한다.

내부 클래스에는 setter메서드와 public생성자가 없기 때문에
객체를 얻기 위해서는 오직 Builder클래스를 통해서만 가능하다.
객체 불변성(Immutablity)을 보장한다.

장점: 한번 값이 지정되면 그 값은 불변한다.
단점: 설계하기가 어렵다.

※외우지 않아도 된다. 롬복의 @Builder어노테이션이 대신 해줌.


생성


내부클래스는 static일수도 아닐 수도 있다. 

외부클래스와 동일한 변수를 가진다.

내부 클래스의 setter메서드가 특이하게 생겼다.
Builder클래스를 얻게 되면, set메서드를 호출할 수 있다.
set메서드로 값을 주면, 다시 Builder클래스를 반환한다.

 

 

 

BuilderVO.java

package com.simple.basic.command;


public class BuilderVO {
	//빌더 패턴의 모형 - 내부 클래스를 생성하고, 외부에서 호출시에 내부클래스에 값을 지정
	//장점-객체의 불변성(값의 변경을 막고, 사용시 가독성이 좋다.)
	
	//1.멤버변수
	private String name;
	private int age;
	
	
	//4.VO의 생성자
	private BuilderVO(Builder builder) {
		this.name=builder.name;
		this.age=builder.age;
	}
	
	//7.외부에서 객체생성을 요구하면 내부에 있는 Builder클래스를 반환
	public static Builder builder() {
		return new Builder();
	}
	
	//2.내부클래스 생성 - 클래스 안에 클래스. inner클래스, nested클래스라고도 한다.
	public static class Builder {
		
		private String name;
		private int age;
		
		//3.생성자 제한
		private Builder() {}
		
		//5.내부 클래스에 setter메서드 생성
		public Builder setName(String name) {
			this.name=name;
			return this;
		}
		
		public Builder setAge(int age) {
			this.age=age;
			return this;
		}
		
		//6. build메서드를 생성 - 나 자신을 외부클래스에 저장하고 반환
		public BuilderVO build() {
			return new BuilderVO(this);
		}
	}

	//8.toString 오버라이딩
	@Override
	public String toString() {
		return "BuilderVO [name=" + name + ", age=" + age + "]";
	}
	
}

-순서를 보면서 이해해야 한다. 

  1. 외부클래스(BuilderVO)에 멤버변수 생성.
  2. 내부클래스(Builder) 생성. 멤버변수는 외부클래스와 동일하다. static
  3. 내부클래스 생성자를 private으로 제한.
  4. 외부클래스 생성자도 private으로 제한. 동시에 내부클래스를 매개변수로 받아 멤버변수에 값을 넣는다.
  5. 내부클래스에 setter메서드를 멤버변수에 맞춰 생성한다. 이때 return을 this로 하여 각각 내부클래스를 반환하도록. public
  6. 내부클래스에 build메서드를 생성. this를 통해 외부클래스 생성자에 내부클래스를 주고 외부클래스를 반환한다. public
  7. 외부에서 객체생성(BuilderVO)을 요구하면 내부에 있는 Builder클래스를 반환하게 return new 내부클래스()로 하는 builder메서드 생성. public static

 

 

BootTest.java

package com.simple.basic;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import com.simple.basic.command.BuilderVO;
import com.simple.basic.command.BuilderVO.Builder;
import com.simple.basic.controller.HomeController;

@SpringBootTest //스프링부트 테스트 클래스
public class BootTest {

//	@Autowired
//	HomeController homeController;
//	
//	@Test
//	public void testCode01() {
//		System.out.println(homeController.home());
//	}
	
	//빌더패턴 객체의 사용
	@Test
	public void testCode02() {
//		Builder xx=BuilderVO.builder();
//		xx=xx.setAge(10);
//		xx=xx.setName("홍길동");
//		BuilderVO vo = xx.build();
		
		
		BuilderVO vo = BuilderVO.builder().setAge(10).setName("홍길동").build();
		System.out.println(vo.toString());
		
		
	}

}

호출순서는 7번---5번의 각 setter들 호출---6번.

각각 반환이

7번:내부클래스(builder()의 반환).

5번:지정한 변수를 받은 내부클래스(setter()의 반환).

6번: 값을 다 받은 내부클래스를 생성자의 매개변수로 받아 멤버변수의 값이 지정된 외부클래스(build()의 반환).

 

이후 값을 변경할 수 없다.

사용했을 때 가독성이 좋다. setter들을 바로바로 확인할 수 있음.

 

 

콘솔출력문

BuilderVO [name=홍길동, age=10]