Spring 🌱

λΉŒλ” νŒ¨ν„΄(Builder Pattern)

z.zzz 2023. 7. 17. 18:57

Entity, Dtoμ—μ„œ 자주 μ‚¬μš©ν•˜λŠ” @Builder μ–΄λ…Έν…Œμ΄μ…˜μ˜ μ—­ν• κ³Ό 의미λ₯Ό ν™•μ‹€νžˆ μ΄ν•΄ν•˜κ³  μ‹Άμ–΄ μ •λ¦¬ν•΄λ³΄μ•˜λ‹€.

 

λΉŒλ” νŒ¨ν„΄

- 객체λ₯Ό 생성할 λ•Œ μ‚¬μš©ν•˜λŠ” λ””μžμΈ νŒ¨ν„΄μ΄λ‹€. μƒμ„±μžμ—μ„œ μΈμžκ°€ λ§Žμ„ λ•Œ λΉŒλ” νŒ¨ν„΄μ˜ μ‚¬μš©μ„ κ³ λ €ν•΄λ³Ό 수 μžˆλ‹€.

- 클래슀λ₯Ό 섀계할 λ•Œ ν•„μˆ˜λ‘œ λ°›μ•„μ•Ό ν•  μΈμžμ™€ μ„ νƒμ μœΌλ‘œ λ°›μ•„μ•Ό ν•  μΈμžκ°€ μ‘΄μž¬ν•œλ‹€λ©΄ 클래슀의 객체λ₯Ό 생성할 λ•Œ, μ‚¬μš©ν•  수 μžˆλŠ” λ””μžμΈ νŒ¨ν„΄μ€ 점측적 μƒμ„±μž νŒ¨ν„΄, μžλ°” 빈즈 νŒ¨ν„΄, λΉŒλ” νŒ¨ν„΄μœΌλ‘œ 총 3가지가 μžˆλ‹€.

 

λ¨Όμ € 점측적 μƒμ„±μž νŒ¨ν„΄λΆ€ν„° μ•Œμ•„λ³΄μž

 

 

점측적 μƒμ„±μž νŒ¨ν„΄

- μƒμ„±μžλ‘œ 데이터λ₯Ό λ°›μ•„ 객체λ₯Ό μƒμ„±ν•œλ‹€.

- User 객체 생성 μ‹œ, ν•„μˆ˜ 값은 id, userName이며 선택 값은 nickName, ageλ‹€.

public class User {

    private int id;           //ID(ν•„μˆ˜)
    private String userName;  //이름(ν•„μˆ˜)
    private String nickname;  //별λͺ…(선택) 
    private int age;          //λ‚˜μ΄(선택)

    public User(int id, String userName){
        this(id, userName, null, 0);
    }

    public User(int id, String userName, String nickname){
        this(id, userName, nickname, 0);
    }

    public User(int id, String userName, String nickname, int age){
        this.id = id;
        this.userName = userName;
        this.nickname = nickname;
        this.age = age;
    }
User user = new User(1, "emily", "emily11", 22);

점측적 μƒμ„±μž νŒ¨ν„΄μ˜ 단점은 λ‹€μŒκ³Ό κ°™λ‹€.

  ⦁ λ§€κ°œλ³€μˆ˜ 쑰합이 λ§Žμ„ 수둝 μƒμ„±μž μˆ˜κ°€ λ§Žμ•„μ§„λ‹€. → 가독성 μ €ν•˜, λΉ„νš¨μœ¨μ  μ½”λ“œ

  ⦁ μƒμ„±μž ν˜ΈμΆœμ‹œ, λ§€κ°œλ³€μˆ˜μ˜ μœ„μΉ˜λ₯Ό μ•Œκ³  μžˆμ–΄μ•Ό ν•œλ‹€.

 

 

μžλ°” 빈즈 νŒ¨ν„΄

- 점측적 μƒμ„±μž νŒ¨ν„΄μ˜ λ‹¨μ μ„ λ³΄μ™„ν•œ νŒ¨ν„΄μ΄λ‹€.

- κΈ°λ³Έ μƒμ„±μžλ‘œ 객체λ₯Ό λ§Œλ“  후에 setter λ©”μ„œλ“œλ‘œ λ§€κ°œλ³€μˆ˜λ₯Ό μ£Όμž…ν•˜λŠ” 방법이닀.

public class User {

    private int id;           //ID(ν•„μˆ˜)
    private String userName;  //이름(ν•„μˆ˜)
    private String nickname;  //별λͺ…(선택) 
    private int age;          //λ‚˜μ΄(선택)

    public User(){
    }

    public void setId(int id){
        this.id = id;
    }

    public void setUserName(String userName){
        this.userName = userName;
    }
    
    public void setNickname(String nickname){
        this.nickname = nickname;
    }
    
    public void setAge(int age){
        this.age = age;
    }
}
User user = new User();
user.setId(1);
user.setUserName("Emily");
user.setNickname("Emily11");
user.setAge(22);

점측적 μƒμ„±μž νŒ¨ν„΄μ— λΉ„ν•΄ 가독성이 μ’‹κ³  setter λ©”μ„œλ“œλ‘œ μ›ν•˜λŠ” λ§€κ°œλ³€μˆ˜μ˜ 값을 μ„€μ •ν•  수 μžˆλ‹€.

κ·ΈλŸ¬λ‚˜ μ½”λ“œ 양이 λŠ˜μ–΄λ‚˜κ³ , 객체λ₯Ό ν•œ 번의 λ©”μ„œλ“œ 호좜둜 생성할 수 μ—†κ²Œ 되며 객체의 일관성이 깨진닀.

 

객체의 일관성이 κΉ¨μ§„λ‹€λŠ” 것은 λ§€κ°œλ³€μˆ˜κ°€ ν•˜λ‚˜ 좔가될 λ•Œλ§ˆλ‹€ μΈμŠ€ν„΄μŠ€κ°€ λ³€ν•œλ‹€λŠ” 것이닀.

일관성이 λ¬΄λ„ˆμ§€λ―€λ‘œ λΆˆλ³€ 클래슀둜 λ§Œλ“œλŠ” 것도 λΆˆκ°€λŠ₯ν•˜λ‹€. λ”°λΌμ„œ 객체가 μ˜λ„μ™€ λ‹€λ₯΄κ²Œ λ³€ν•  κ°€λŠ₯성이 μžˆλ‹€.

 

 

λΉŒλ” νŒ¨ν„΄

- 점측적 μƒμ„±μž νŒ¨ν„΄κ³Ό μžλ°” 빈즈 νŒ¨ν„΄μ˜ μž₯점을 κ²°ν•©ν•œ 객체 생성 νŒ¨ν„΄μ΄λ‹€.

- μ •λ³΄λŠ” μžλ°” 빈즈 νŒ¨ν„΄μ²˜λŸΌ λ°›μœΌλ©° 가독성을 높이고, κ°μ²΄λŠ” 점측적 μƒμ„±μž νŒ¨ν„΄μ²˜λŸΌ μƒμ„±ν•˜λ©° 객체의 일관성을 μœ μ§€ν•œλ‹€.

- λ³„λ„μ˜ Builder 클래슀λ₯Ό λ§Œλ“€μ–΄ ν•„μˆ˜λ³€μˆ˜λŠ” μƒμ„±μžλ‘œ, μ„ νƒλ³€μˆ˜λŠ” λ©”μ„œλ“œλ‘œ 받은 ν›„, build λ©”μ„œλ“œλ‘œ μΈμŠ€ν„΄μŠ€λ₯Ό λ¦¬ν„΄ν•˜λ©° 객체λ₯Ό μƒμ„±ν•œλ‹€.

public class User {

    private int id;           //ID(ν•„μˆ˜)
    private String userName;  //이름(ν•„μˆ˜)
    private String nickname;  //별λͺ…(선택) 
    private int age;          //λ‚˜μ΄(선택)

    public static class Builder(){
    	private int id;           
        private String userName;  
        private String nickname;  
        private int age; 
        
        //ν•„μˆ˜λ³€μˆ˜λŠ” Builder μƒμ„±μžλ‘œ μ£Όμž…
        public Builder(String id, String userName) {
            this.id = id;
            this.userName = userName;
        }
        
        //μ„ νƒλ³€μˆ˜λŠ” λΉŒλ” 클래슀의 ν•„λ“œμ„ setν•œ ν›„ λΉŒλ” 객체λ₯Ό λ°˜ν™˜
        public Builder setNickname(String nickname) {
            this.nickname = nickname;
            return this;
        }
        
        public Builder setAge(String age) {
            this.age = age;
            return this;
        }
        
        //λΉŒλ” λ©”μ„œλ“œ
        public User build() {
            return new User(this);  //this : 객체 μžμ‹ μ„ κ°€λ¦¬ν‚€λŠ” 레퍼런슀 λ³€μˆ˜
        }
    }
}
User user = User.builder(1,"Emily")
    .nickname("Emily11")
    .age(22)
    .build();

λΉŒλ” λ©”μ„œλ“œ 이후엔 setter 같은 값을 λ³€κ²½ν•  수 μžˆλŠ” λ©”μ„œλ“œκ°€ μ—†μœΌλ―€λ‘œ λ©€λ²„λ³€μˆ˜λ₯Ό λ³€κ²½ν•  수 μ—†λ‹€. λ”°λΌμ„œ λ°μ΄ν„°μ˜ 일관성, 객체의 λΆˆλ³€μ„±μ„ 보μž₯ν•œλ‹€.

 

 

λΉŒλ” νŒ¨ν„΄(Builder Pattern)의 μž₯점

1. ν•„μš”ν•œ λ°μ΄ν„°λ§Œ μ„€μ •ν•  수 μžˆλ‹€.

2. μœ μ—°μ„±μ„ 확보할 수 μžˆλ‹€.

3. 가독성을 높일 수 μžˆλ‹€.

4. λ³€κ²½ κ°€λŠ₯성을 μ΅œμ†Œν™”ν•  수 μžˆλ‹€.

5. λ°μ΄ν„°μ˜ μˆœμ„œμ— 상관없이 객체λ₯Ό 생성할 수 μžˆλ‹€.

6. build()ν•¨μˆ˜κ°€ null인지 μ²΄ν¬ν•΄μ£Όλ―€λ‘œ 검증이 κ°€λŠ₯ν•˜λ‹€.

 

 

@Builder

Lombok ν”ŒλŸ¬κ·ΈμΈμ—μ„œ μ§€μ›ν•˜λŠ” μ–΄λ…Έν…Œμ΄μ…˜μœΌλ‘œ λΉŒλ” 클래슀λ₯Ό μžλ™μœΌλ‘œ λ§Œλ“€ 수 μžˆλ‹€.

ν΄λž˜μŠ€λ‚˜ μƒμ„±μž μœ„μ— @Builder μ–΄λ…Έν…Œμ΄μ…˜μ„ 뢙이면 λΉŒλ”κ°€ 생긴닀.

(μƒμ„±μž μœ„μ— 뢙이면, μƒμ„±μžμ— ν¬ν•¨λœ ν•„λ“œλ§Œ λΉŒλ”μ— ν¬ν•¨λœλ‹€.)

@Builder
public class User {
    private int id;           
    private String userName;  
    private String nickname;  
    private int age;          
}
User user = User.builder()  //λΉŒλ”ν΄λž˜μŠ€ μƒμ„±μž
    .id(1)
    .name("Emily")
    .nickname("Emily11")
    .age(22)
    .build();

 

λΉŒλ” νŒ¨ν„΄μ„ μ‚¬μš©ν•˜μ§€ μ•Šμ•„λ„ λ˜λŠ” 경우

λŒ€λΆ€λΆ„μ˜ μΌ€μ΄μŠ€μ—μ„  λΉŒλ” νŒ¨ν„΄μ„ μ μš©ν•˜λŠ” 게 μ’‹λ‹€.

κ·ΈλŸ¬λ‚˜ μƒμ„±μžμ— ν•„μš”ν•œ λ§€κ°œλ³€μˆ˜μ˜ μˆ˜κ°€ 일반적으둜 4κ°œλ³΄λ‹€ 적닀면 λΉŒλ”λ₯Ό 쓰지 μ•Šμ•„λ„ λœλ‹€.

- λΉŒλ”λŠ” λΉŒλ”κ°€ 뢙은 클래슀의 λͺ¨λ“  ν•„λ“œλ₯Ό λ³΅μ‚¬ν•˜λ―€λ‘œ μ½”λ“œκ°€ μž₯ν™©ν•˜κ³ (verbose) μ€‘λ³΅λœλ‹€.