Post

[Java] ๋นŒ๋” ํŒจํ„ด(Builder Pattern)

๐Ÿ“Œ ๋“ค์–ด๊ฐ€๋ฉฐ

๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ ๋งŽ์€ ์ƒ์„ฑ์ž๋กœ ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค๋‹ค ๋ณด๋ฉด new Car("Toyota", "Camry", 2022, "Blue", ...)์ฒ˜๋Ÿผ ๋˜์–ด, ์–ด๋–ค ๊ฐ’์ด ๋ฌด์Šจ ์ธ์ž์ธ์ง€ ํ—ท๊ฐˆ๋ฆฌ๊ณ  ์ˆœ์„œ๋ฅผ ์‹ค์ˆ˜ํ•˜๊ธฐ ์‰ฝ๋‹ค. ์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ๊ฒƒ์ด Builder ํŒจํ„ด์ด๋‹ค.

Builder ํŒจํ„ด์ด๋ž€? ๊ฐ์ฒด์˜ ์ƒ์„ฑ ๊ณผ์ •์„ ๋ณ„๋„ ํด๋ž˜์Šค๋กœ ๋ถ„๋ฆฌํ•ด, ๋‹ค์–‘ํ•œ ์†์„ฑ์„ ๊ฐ€์ง„ ๊ฐ์ฒด๋ฅผ ๋‹จ๊ณ„์ ์œผ๋กœ ์ƒ์„ฑํ•˜๋Š” ํŒจํ„ด. ํ•„์š”ํ•œ ์†์„ฑ๋งŒ ๊ณจ๋ผ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์–ด ๊ฐ€๋…์„ฑ์ด ์ข‹๋‹ค.

์žฅ์  3๊ฐ€์ง€:

์žฅ์ ์„ค๋ช…
๊ฐ€๋…์„ฑ ํ–ฅ์ƒ๊ฐ ์†์„ฑ์„ ๋ฉ”์†Œ๋“œ๋กœ ์„ค์ • โ†’ ๋ฌด์Šจ ๊ฐ’์„ ๋„ฃ๋Š”์ง€ ๋ช…ํ™•
ํ™•์žฅ์„ฑ์ƒˆ ์†์„ฑ ์ถ”๊ฐ€ ์‹œ ๊ธฐ์กด ์ฝ”๋“œ ๋ณ€๊ฒฝ ์ตœ์†Œํ™”
๋ถˆ๋ณ€์„ฑ ์œ ์ง€๊ฐ์ฒด๋ฅผ ๋ถˆ๋ณ€ํ•˜๊ฒŒ ๋งŒ๋“ค์–ด ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋“œ์—์„œ ์•ˆ์ „

1. ๊ธฐ๋ณธ ์˜ˆ์‹œ

์ •์  ๋‚ด๋ถ€ ํด๋ž˜์Šค Builder๋ฅผ ๋‘๊ณ , ๊ฐ ์„ค์ • ๋ฉ”์†Œ๋“œ๊ฐ€ ์ž๊ธฐ ์ž์‹ (this)์„ ๋ฐ˜ํ™˜ํ•ด ์ฒด์ด๋‹์„ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•œ๋‹ค.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
public class Car {
    private String brand;
    private String model;
    private int year;
    private String color;

    private Car(Builder builder) {           // ์ƒ์„ฑ์ž๋Š” private
        this.brand = builder.brand;
        this.model = builder.model;
        this.year  = builder.year;
        this.color = builder.color;
    }

    public static class Builder {
        private String brand;
        private String model;
        private int year;
        private String color;

        public Builder(String brand, String model) {   // ํ•„์ˆ˜๊ฐ’์€ ์ƒ์„ฑ์ž๋กœ
            this.brand = brand;
            this.model = model;
        }

        public Builder year(int year)     { this.year = year;   return this; }  // ์„ ํƒ๊ฐ’
        public Builder color(String color){ this.color = color; return this; }

        public Car build() {                 // ์ตœ์ข… ๊ฐ์ฒด ์ƒ์„ฑ
            return new Car(this);
        }
    }
}

// ์‚ฌ์šฉ ์˜ˆ์‹œ
Car car = new Car.Builder("Toyota", "Camry")   // ํ•„์ˆ˜
                .year(2022)                     // ์„ ํƒ
                .color("Blue")                  // ์„ ํƒ
                .build();

๐Ÿ’ก ํ•„์ˆ˜๊ฐ’์€ Builder ์ƒ์„ฑ์ž๋กœ, ์„ ํƒ๊ฐ’์€ ์ฒด์ด๋‹ ๋ฉ”์†Œ๋“œ๋กœ ๋ฐ›๋Š” ๊ฒƒ์ด ์ผ๋ฐ˜์ ์ธ ํŒจํ„ด์ด๋‹ค.


2. Lombok์œผ๋กœ ๋” ๊ฐ„๊ฒฐํ•˜๊ฒŒ

Lombok์˜ @Builder ์• ๋…ธํ…Œ์ด์…˜์„ ์“ฐ๋ฉด Builder ํด๋ž˜์Šค๋ฅผ ์ž๋™ ์ƒ์„ฑํ•ด์ค€๋‹ค.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import lombok.Builder;
import lombok.Getter;

@Getter
@Builder
public class Car {
    private String brand;
    private String model;
    private int year;
    private String color;
}

// ์‚ฌ์šฉ ์˜ˆ์‹œ
Car car = Car.builder()
             .brand("Toyota")
             .model("Camry")
             .year(2022)
             .color("Blue")
             .build();

์• ๋…ธํ…Œ์ด์…˜ ํ•˜๋‚˜๋กœ ์œ„์˜ ์žฅํ™ฉํ•œ Builder ์ฝ”๋“œ๋ฅผ ๋Œ€์ฒดํ•˜๋‹ˆ, ์ค‘๋ณต์„ ํฌ๊ฒŒ ์ค„์ผ ์ˆ˜ ์žˆ๋‹ค.


3. ํ•œ ๊ฑธ์Œ ๋” โ€” Fluent Interface

Builder์— Fluent Interface(๋ฉ”์†Œ๋“œ ์ฒด์ด๋‹์œผ๋กœ ๋ฌธ์žฅ์ฒ˜๋Ÿผ ์ฝํžˆ๋Š” ์Šคํƒ€์ผ)๋ฅผ ์ ์šฉํ•˜๋ฉด ์ฝ”๋“œ๊ฐ€ ๋” ์ž์—ฐ์Šค๋Ÿฌ์›Œ์ง„๋‹ค.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public class Car {
    private String brand;
    private String model;
    private int year;
    private String color;

    private Car() {}

    public static CarBuilder builder() {
        return new CarBuilder();
    }

    public static class CarBuilder {
        private final Car car = new Car();
        private CarBuilder() {}

        public CarBuilder brand(String brand) { car.brand = brand; return this; }
        public CarBuilder model(String model) { car.model = model; return this; }
        public CarBuilder year(int year)      { car.year = year;   return this; }
        public CarBuilder color(String color) { car.color = color; return this; }

        public Car build() { return car; }
    }
}

// ์‚ฌ์šฉ ์˜ˆ์‹œ
Car car = Car.builder()
             .brand("Toyota")
             .model("Camry")
             .year(2022)
             .color("Blue")
             .build();

๋ฉ”์†Œ๋“œ ํ˜ธ์ถœ์ด ์—ฐ๊ฒฐ๋˜์–ด ์ž์—ฐ์Šค๋Ÿฌ์šด ๋ฌธ์žฅ ํ˜•ํƒœ๋กœ ์ฝํžˆ๋‹ˆ, ๊ฐ€๋…์„ฑ์ด ์ข‹์•„์ง€๊ณ  ์ฝ”๋“œ ์ž‘์„ฑ๋„ ์ฆ๊ฑฐ์›Œ์ง„๋‹ค.


๐Ÿ“ ์ •๋ฆฌ

1
2
3
4
5
6
Builder ํŒจํ„ด
โ”œโ”€ ๋ชฉ์     ๋งค๊ฐœ๋ณ€์ˆ˜ ๋งŽ์€ ์ƒ์„ฑ์ž์˜ ๊ฐ€๋…์„ฑยท์‹ค์ˆ˜ ๋ฌธ์ œ ํ•ด๊ฒฐ
โ”œโ”€ ๊ตฌ์กฐ    ๋‚ด๋ถ€ Builder ํด๋ž˜์Šค + ์ฒด์ด๋‹(return this) + build()
โ”œโ”€ ํ•„์ˆ˜/์„ ํƒ  ํ•„์ˆ˜๊ฐ’์€ ์ƒ์„ฑ์ž, ์„ ํƒ๊ฐ’์€ ์ฒด์ด๋‹ ๋ฉ”์†Œ๋“œ
โ”œโ”€ Lombok  @Builder๋กœ ์ž๋™ ์ƒ์„ฑ (์ค‘๋ณต ์ œ๊ฑฐ)
โ””โ”€ ํ™•์žฅ    Fluent Interface๋กœ ๋ฌธ์žฅ์ฒ˜๋Ÿผ ์ฝํžˆ๊ฒŒ
๊ฐœ๋…ํ•œ ์ค„ ์ •์˜
Builder ํŒจํ„ด๊ฐ์ฒด ์ƒ์„ฑ์„ ๋‹จ๊ณ„๋ณ„๋กœ ๋ถ„๋ฆฌํ•˜๋Š” ๋””์ž์ธ ํŒจํ„ด
์ฒด์ด๋‹(return this)์„ค์ • ๋ฉ”์†Œ๋“œ๊ฐ€ ์ž์‹ ์„ ๋ฐ˜ํ™˜ํ•ด ์—ฐ๊ฒฐ
@BuilderLombok์ด Builder๋ฅผ ์ž๋™ ์ƒ์„ฑ

Builder ํŒจํ„ด์€ โ€œ์ƒ์„ฑ์ž ์ง€์˜ฅโ€์„ ๋ฒ—์–ด๋‚˜๊ฒŒ ํ•ด์ฃผ๋Š” ์‹ค์šฉ์ ์ธ ํŒจํ„ด์ด๋‹ค. ์ˆœ์ˆ˜ ์ž๋ฐ”๋กœ ๊ตฌํ˜„ํ•  ์ˆ˜๋„ ์žˆ์ง€๋งŒ, ์‹ค๋ฌด์—์„œ๋Š” Lombok์˜ @Builder ํ•œ ์ค„๋กœ ๊ฐ„๊ฒฐํ•˜๊ฒŒ ์“ฐ๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ๋‹ค.

This post is licensed under CC BY 4.0 by the author.

Comments powered by Disqus.