μΉ΄ν…Œκ³ λ¦¬ μ—†μŒ

[Gof의 λ””μžμΈνŒ¨ν„΄] λΉŒλ” νŒ¨ν„΄

λ°”λž„ 희 2022. 10. 25. 17:39

πŸ™ λΉŒλ” νŒ¨ν„΄μ΄λž€?

- λ‹€μ–‘ν•œ κ΅¬μ„±μ˜ μΈμŠ€ν„΄μŠ€λ“€μ„ λ™μΌν•œ 과정을 거쳐 생성할 수 μžˆλ„λ‘ ν•˜λŠ” νŒ¨ν„΄

 

πŸ™ λΉŒλ” νŒ¨ν„΄μ˜ ν•„μš”μ„±?

- λ³΅μž‘ν•œ 객체λ₯Ό μƒμ„±ν•˜λŠ” ν΄λž˜μŠ€μ™€ ν‘œν˜„ν•˜λŠ” 클래슀λ₯Ό λΆ„λ¦¬ν•΄μ„œ λ™μΌν•œ μ ˆμ°¨μ—μ„œλ„ μ„œλ‘œ λ‹€λ₯Έ ν‘œν˜„μ„ μƒμ„±ν•˜λŠ” 방법을 제곡

- 생성해야 ν•˜λŠ” 객체가 optional ν•œ 속성을 많이 κ°€μ§ˆ λ•Œ 더 μ’‹μŒ

- ν•„μš”μ—†λŠ” νŒŒλΌλ―Έν„°λ“€μ— λŒ€ν•΄μ„œ 일일이 null 값을 λ„˜κΈ°μ§€ μ•Šμ•„λ„ 됨

- Optional ν•œ μΈμžκ°€ λ§Žμ•„μ§€λ©΄ νƒ€μž…κ³Ό μˆœμ„œμ— λŒ€ν•œ 관리가 μ–΄λ €μš΄λ° 이λ₯Ό ν•΄κ²°ν•΄μ€Œ

 

πŸ™ λΉŒλ” νŒ¨ν„΄ κ΅¬ν˜„ν•˜κΈ°

public class Lecture {

    String startTime;

    String endTime;

    String day;

    String professorName;

    String title;

    String content;

    String bookName;

    String classRoom;}

도메인은 μœ„μ™€ κ°™λ‹€. 만일 κ°•μ˜μ— 책이 ν•„μš”ν•˜μ§€ μ•Šκ±°λ‚˜, 온라인 μˆ˜μ—…μ΄λΌμ„œ classRoom 이 μ‘΄μž¬ν•˜μ§€ μ•ŠλŠ”λ‹€λ©΄ ν•΄λ‹Ή 값듀은 λͺ¨λ‘ null이 λ˜μ–΄μ•Ό ν•œλ‹€. λ”°λΌμ„œ 점측적인 μƒμ„±μž νŒ¨ν„΄μ„ μ΄μš©ν•΄ μš”κ΅¬μ‚¬ν•­μ„ λ§Œμ‘±μ‹œν‚¬ μˆ˜λ„ μžˆλ‹€.

 

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

- μ˜€λ²„λ‘œλ”©μ„ ν†΅ν•΄μ„œ μƒμ„±μžλ₯Ό μ—¬λŸ¬κ°œ λ§Œλ“œλŠ” 것

public Lecture(String startTime, 
                   String endTime, 
                   String day, 
                   String professorName,
                   String title, 
                   String content
    ) {
        this.startTime = startTime;
        this.endTime = endTime;
        this.day = day;
        this.professorName = professorName;
        this.title = title;
        this.content = content;
    }
    

    public Lecture(String startTime,
                   String endTime, 
                   String day, 
                   String professorName, 
                   String title, 
                   String content,
                   String bookName, 
                   String classRoom) {
        this.startTime = startTime;
        this.endTime = endTime;
        this.day = day;
        this.professorName = professorName;
        this.title = title;
        this.content = content;
        this.bookName = bookName;
        this.classRoom = classRoom;
    }

μœ„μ™€ 같이 Optional ν•œ νŒŒλΌλ―Έν„°λ“€μ„ ν•΄κ²°ν•  수 μžˆλ‹€. κ·ΈλŸ¬λ‚˜, 이와 같이 μƒμ„±μžλ₯Ό μ •μ˜ν•˜κ²Œ λœλ‹€λ©΄ 맀번 μƒˆλ‘œμš΄ μƒμ„±μžλ₯Ό λ§Œλ“€κ±°λ‚˜ null 값을 일일이 λ„˜κ²¨μ€˜μ•Ό ν•˜λŠ” λ¬Έμ œκ°€ μžˆλ‹€. λ˜ν•œ μΆ”ν›„ μ½”λ“œλ₯Ό λ³Ό λ•Œ μ–΄λ–€ ν•„λ“œμ— 값을 λ„£μ—ˆλŠ”μ§€ ν•œλˆˆμ— μ•Œμ•„λ³΄κΈ° μ–΄λ ΅λ‹€. κ·Έλ ‡λ‹€λ©΄ 일일이 λͺ¨λ‘ setter λ₯Ό μ΄μš©ν•˜λ©΄ λ˜μ§€ μ•Šμ„κΉŒ?

 

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

Lecture lecture = new Lecture();
lecture.setTitle("ν•œκ΅­ 문학사");
lecture.setContent("ν•œκ΅­ 문학사에 λŒ€ν•΄μ„œ 온라인으둜 λ°°μ›λ‹ˆλ‹€.");
lecture.setBookName("ν•œκ΅­ 문학사 II");
lecture.setProfessorName("κΉ€μ² μˆ˜");

μ΄λŠ” 일일이 Null 을 λ„˜κ²¨μ£Όμ§€ μ•Šμ•„λ„ 되고, μ„ νƒμ μœΌλ‘œ νŒŒλΌλ―Έν„°λ₯Ό λ„˜κ²¨μ€„ 수 μžˆκΈ°μ— μ–΄λŠ μ •λ„μ˜ λ¬Έμ œλŠ” 해결됐닀.

κ·ΈλŸ¬λ‚˜, ν•¨μˆ˜ 호좜이 νŒŒλΌλ―Έν„°μ˜ 개수만큼 이루어지고 ν•œλ²ˆμœΌλ‘œ 생성할 수 μ—†λ‹€.

λ˜ν•œ, immutable ν•˜μ§€ μ•ŠκΈ° λ•Œλ¬Έμ— 일관성이 깨질 μš°λ €κ°€ μ‘΄μž¬ν•œλ‹€. 

 

 

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

public interface LectureBuilder {

    LectureBuilder startTime(String statTime);

    LectureBuilder endTime(String endTime);

    LectureBuilder day(String day);

    LectureBuilder professorName(String professorName);

    LectureBuilder title(String title);

    LectureBuilder content(String content);

    LectureBuilder bookName(String bookName);

    LectureBuilder classRoom(String classRoom);

    Lecture getInstance();

}

μœ„μ˜ λ‹€μ΄μ–΄κ·Έλž¨μ—μ„œ Builder 에 ν•΄λ‹Ήν•˜λŠ” μΈν„°νŽ˜μ΄μŠ€λ₯Ό μ •μ˜ν•œλ‹€. μ΄λŠ” 객체λ₯Ό μƒμ„±ν•˜κΈ° μœ„ν•œ step 을 μ •μ˜ν•˜λŠ” 것이닀. 

λ”°λΌμ„œ λͺ¨λ“  λ©”μ„œλ“œλ“€μ˜ λ°˜ν™˜ νƒ€μž…μ΄ builder 인 것이닀. builder 을 λ°˜ν™˜ν•˜μ—¬ κ³„μ†ν•΄μ„œ νŒŒλΌλ―Έν„°μ˜ 값을 λ°›λŠ” 것이닀.

 

public class DefaultLectureBuilder implements LectureBuilder{

    String startTime;

    String endTime;

    String day;

    String professorName;

    String title;

    String content;

    String bookName;

    String classRoom;

    @Override
    public LectureBuilder startTime(String statTime) {
        this.startTime = statTime;
        return this;
    }

    @Override
    public LectureBuilder endTime(String endTime) {
        this.endTime = endTime;
        return this;
    }

    @Override
    public LectureBuilder day(String day) {
        this.day = day;
        return this;
    }

    @Override
    public LectureBuilder professorName(String professorName) {
        this.professorName = professorName;
        return this;
    }

    @Override
    public LectureBuilder title(String title) {
        this.title = title;
        return this;
    }

    @Override
    public LectureBuilder content(String content) {
        this.content = content;
        return this;
    }

    @Override
    public LectureBuilder bookName(String bookName) {
        this.bookName = bookName;
        return this;
    }

    @Override
    public LectureBuilder classRoom(String classRoom) {
        this.classRoom = classRoom;
        return this;
    }

    @Override
    public Lecture getInstance() {
        return new Lecture(startTime, endTime, day, professorName, title, content, bookName, classRoom
        );
    }
}

μœ„μ˜ λ‹€μ΄μ–΄κ·Έλž¨μ—μ„œ ConcreteBuilder 에 ν•΄λ‹Ήν•œλ‹€. 

이λ₯Ό λ°”νƒ•μœΌλ‘œ 객체λ₯Ό μƒμ„±ν•΄λ³΄μž.

 

Lecture first = new DefaultLectureBuilder().title("ν•œκ΅­ λ¬Έν•™μ‚¬μ˜ 이해")
        .bookName("ν•œκ΅­ 문학사 II")
        .content("ν•œκ΅­μ˜ 문학사에 λŒ€ν•΄μ„œ 온라인으둜 λ°°μ›λ‹ˆλ‹€.")
        .professorName("κΉ€μ² μˆ˜")
        .day("수")
        .startTime("13")
        .endTime("15")
        .getInstance();

μœ„μ™€ 같이 객체λ₯Ό 생성해주면 λœλ‹€. . 을 μ΄μš©ν•˜μ—¬ 계속 이을 수 μžˆλŠ” μ΄μœ λŠ” λͺ¨λ“  μΈμžλ“€μ˜ λ°˜ν™˜κ°’μ΄ builder 이기 λ•Œλ¬Έμ΄λ‹€.

λ§ˆμ§€λ§‰μ—λŠ” getInstance λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•˜μ—¬ 객체λ₯Ό μƒμ„±ν•œλ‹€.

 

μœ„μ˜ λ‹€μ΄μ–΄κ·Έλž¨μ— ν•΄λ‹Ήν•˜λŠ” Director λ₯Ό μ΄μš©ν•˜λ©΄ ν΄λΌμ΄μ–ΈνŠΈ μ½”λ“œλ₯Ό 쀄일 수 μžˆλ‹€.

 

public class LectureDirector{

    private LectureBuilder lectureBuilder;

    public LectureDirector(LectureBuilder lectureBuilder){
        this.lectureBuilder = lectureBuilder;
    }

    public Lecture communicativeEnglish(){
        return lectureBuilder.professorName("κΉ€λ―Έμ˜")
                .startTime("13")
                .endTime("15")
                .bookName("Communicative English part I")
                .title("ꡐ양 μ˜μ–΄")
                .content("ν•„μˆ˜ ꡐ양 μ˜μ–΄ μˆ˜μ—…μž…λ‹ˆλ‹€.")
                .getInstance();
    }

}
LectureDirector lectureDirector = new LectureDirector(new DefaultLectureBuilder());
Lecture newLecture = lectureDirector.communicativeEnglish();

 

πŸ™ λΉŒλ” νŒ¨ν„΄μ—μ„œ ν•„μˆ˜λ‘œ μž…λ ₯λ°›μ•„μ•Ό ν•˜λŠ” νŒŒλΌλ―Έν„° μ§€μ •ν•˜κΈ°

public DefaultLectureBuilder(String startTime, 
                             String endTime,
                             String professorName){
    this.startTime = startTime;
    this.endTime = endTime;
    this.professorName = professorName;
}

 

ν•„μˆ˜λ‘œ μž…λ ₯λ°›μ•„μ•Ό ν•˜λŠ” νŒŒλΌλ―Έν„°λ“€μ€ λΉŒλ”μ˜ μƒμ„±μžμ— 미리 λ„£μ–΄λ‘”λ‹€. 이후 μ„ νƒμ μœΌλ‘œ μž…λ ₯λ°›λŠ” νŒŒλΌλ―Έν„°λ“€μ— λŒ€ν•΄μ„œλ§Œ λΉŒλ” νŒ¨ν„΄μ„ μ μš©ν•œλ‹€. μ΄λŠ” μœ„μ™€ λ™μΌν•˜λ‹ˆ μƒλž΅ν•˜κ² λ‹€.

 

πŸ™ λΉŒλ” νŒ¨ν„΄μ˜ μž₯점/단점

μž₯점

- 가독성이 μ’‹λ‹€

- 객체의 일관성을 κΉ¨μ§€ μ•Šμ„ 수 μžˆλ‹€

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

- λΆˆλ³€μ„±μ„ 확보할 수 μžˆλ‹€

- 순차적인 단계λ₯Ό κ°•μ œν•  수 μžˆλ‹€.

//1
LectureBuilder title(String title);

//2
SecondLectureBuilder title(String title);

 

1번이 μ•„λ‹Œ 2번처럼 μƒˆλ‘œμš΄ λΉŒλ”λ₯Ό λ°˜ν™˜κ°’μœΌλ‘œ μ§€μ •ν•˜κ²Œ 되면 ν•΄λ‹Ή λΉŒλ”μ— μ‘΄μž¬ν•˜λŠ” λ©”μ„œλ“œλ₯Ό μ‚¬μš©ν•˜λ„λ‘ κ°•μ œν•  수 μžˆλ‹€.

즉, 객체의 title 을 μ§€μ •ν•˜κ³  λ‚˜μ„œλŠ” λ‹€λ₯Έ λΉŒλ”λ‘œ λ„˜μ–΄κ°€λ„λ‘ ν•˜λŠ” 것이닀.

 

단점

- μΈμŠ€ν„΄μŠ€λ₯Ό λ§Œλ“€μ–΄μ„œ μ‚¬μš©ν•΄μ•Ό ν•œλ‹€

- 디렉토리 ꡬ쑰가 λ³΅μž‘ν•΄μ§ˆ 수 μžˆλ‹€.

 

πŸ™ μŠ€ν”„λ§μ—μ„œμ˜ λΉŒλ” νŒ¨ν„΄

@Builder

@Builder
public class BuildMe {

    private String username;
    private int age;

}

μœ„μ™€ 같이 Builder μ–΄λ…Έν…Œμ΄μ…˜μ„ 뢙이면 μ•„λž˜μ™€ 같이 컴파일 μ‹œμ— μ–΄λ…Έν…Œμ΄μ…˜μ΄ λ°”μ΄νŠΈμ½”λ“œλ₯Ό λ°”κΏ”μ€€λ‹€.

public class BuildMe {
    private String username;
    private int age;

    BuildMe(String username, int age) {
        this.username = username;
        this.age = age;
    }

    public static BuildMe.BuildMeBuilder builder() {
        return new BuildMe.BuildMeBuilder();
    }

    public static class BuildMeBuilder {
        private String username;
        private int age;

        BuildMeBuilder() {
        }

        public BuildMe.BuildMeBuilder username(String username) {
            this.username = username;
            return this;
        }

        public BuildMe.BuildMeBuilder age(int age) {
            this.age = age;
            return this;
        public BuildMe build() {
            return new BuildMe(this.username, this.age);
        }

        public String toString() {
            return "BuildMe.BuildMeBuilder(username=" + this.username + ", age=" + this.age + ")";
        }
    }
}

 

 

πŸ™ μ°Έκ³ 

https://dev-youngjun.tistory.com/197

 

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

1. λΉŒλ” νŒ¨ν„΄μ΄λž€? 생성과 κ΄€λ ¨λœ λ””μžμΈ νŒ¨ν„΄μœΌλ‘œ, λ™μΌν•œ ν”„λ‘œμ„ΈμŠ€λ₯Ό 거쳐 λ‹€μ–‘ν•œ κ΅¬μ„±μ˜ μΈμŠ€ν„΄μŠ€λ₯Ό λ§Œλ“œλŠ” 방법 1-1. μ •μ˜(Definition) GoF λ””μžμΈ νŒ¨ν„΄ 쀑 μƒμ„± νŒ¨ν„΄μ— ν•΄λ‹Ήν•œλ‹€. λΉŒλ” νŒ¨ν„΄μ€

dev-youngjun.tistory.com

https://velog.io/@park2348190/Lombok-Builder%EC%9D%98-%EB%8F%99%EC%9E%91-%EC%9B%90%EB%A6%AC

 

Lombok @Builder의 λ™μž‘ 원리

λ³΄μΌλŸ¬ν”Œλ ˆμ΄νŠΈ λ©”μ„œλ“œ(getter/setter, constructor λ“±)λ₯Ό 직접 μž‘μ„±ν•˜μ§€ μ•Šμ•„λ„ λŒ€μ‹  μž‘μ„±ν•΄μ£ΌλŠ” Lombokλ₯Ό μ΅œκ·Όμ— 많이 ν™œμš©ν•˜κ³  μžˆλ‹€. κ·Έλ‚˜λ§ˆ setter λ©”μ„œλ“œκ°™μ€ κ²½μš°λŠ” 값을 λ³€κ²½μ‹œν‚€λŠ” λ©”μ„œλ“œλŠ” κ·Έ λͺ©

velog.io