컴퓨터과학/0 + 소프트웨어 아키텍처(디자인 패턴)

[소프트웨어 아키텍처] 12. 빌더 패턴(Builder Pattern -java)

힘들면힘을내는쿼카 2022. 12. 6. 22:30
728x90
반응형

빌더 패턴(Builder Pattern)

짜장면을 여러 단계로 나누어서 먹을수 있도록 먹는 방법을 캡슐화하고 싶다면…?
짜잔! 빌더 패턴을 사용하면 됩니다.!!

반복자 패턴을 기억하시나요?
반복자 패턴을 사용하면 컬렉션의 구현방법을 노출하지 않으면서 집합체 내의 모든 항목에 접근할 수 있습니다.
쉽게 이야기 하면, 반복 작업을 별도의 객체로 캡슐화해서 컬렉션의 내부 구조를 클라이언트로부터 보호할 수 있습니다.

빌더 패턴도 동일한 아이디어를 적용합니다.!
빌더를 캡슐화해서 클라이언트가 빌더에게 구조를 만들어 달라고 요청하는 것 입니다...!

빌터 패턴 구조

  • AbstractBuilder
    • 빌더패턴의 대상이 되는 클래스
  • ConcreteBuilder
    • AbstractBuilder에 필요한 메소드를 구현한 클래스
    • 빌더패턴을 만드는 메소드를 캡슐화한 AbstractBuilder의 내부 클래스

🥕 당근 마켓 게시판 DTO 빌더패턴 구현

당근마켓 인턴으로 근무하고 있는 당신!
사수님이 당근마켓 게시판에 필요한 DTO를 개발해달라고 합니다.
아직 정확한 데이터가 정립되지 않아 기획자에 의해 언제든지 바뀔 수 있다고 합니다..!

빌더패턴을 사용하여 실력 발휘를 해봅시다..!!! 😎

CarrotBoard

import lombok.ToString;

@ToString(of = {"title", "content", "author", "carrotPay", "pictureName"})
public class CarrotBoard {
    private String title;
    private String content;
    private String author;
    private boolean carrotPay;
    private String pictureName;

    private CarrotBoard(String title, String content, String author, boolean carrotPay, String pictureName) {
        this.title = title;
        this.content = content;
        this.author = author;
        this.carrotPay = carrotPay;
        this.pictureName = pictureName;
    }

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

    public static class CarrotBoardBuilder {

        private String title;
        private String content;
        private String author;
        private int price;
        private boolean carrotPay = false;
        private String pictureName;

        private CarrotBoardBuilder() {
        }

        public CarrotBoardBuilder title(String title) {
            this.title = title;
            return this;
        }

        public CarrotBoardBuilder content(String content) {
            this.content = content;
            return this;
        }

        public CarrotBoardBuilder price(int price) {
            this.price = price;
            return this;
        }

        public CarrotBoardBuilder author(String author) {
            this.author = author;
            return this;
        }

        public CarrotBoardBuilder carrotPay(boolean carrotPay) {
            this.carrotPay = carrotPay;
            return this;
        }

        public CarrotBoardBuilder pictureName(String pictureName) {
            this.pictureName = pictureName;
            return this;
        }

        public CarrotBoard build() {
            return new CarrotBoard(this.title, this.content, this.author, this.carrotPay, this.pictureName);
        }
    }
}

Client

public class Client {
    public static void main(String[] args) {
        CarrotBoard carrotBoard = CarrotBoard.builder()
                .title("2022 맥북프로(실버) 14")
                .price(2100000)
                .author("쿼카")
                .content("2022 맥북프로 14 팝니다.")
                .pictureName("맥북프로 사진")
                .build();

        System.out.println(carrotBoard);
    }
}

결과

CarrotBoard(title=2022 맥북프로(실버) 14, content=2022 맥북프로 14 팝니다., 
author=쿼카, carrotPay=false, pictureName=맥북프로 사진)

롬복(lombok) 사용

당신의 사수가 빌더 패턴으로 50개의 DTO를 개발해달라고 요청했습니다…
저런식으로 개발 하다가는 손가락 관절염에 걸릴꺼에요.… 🙉

여기서 lombok을 사용하면 고민이 해결됩니다.

import lombok.Builder; //롬북 패키지를 사용합니다.

public class Member {
    private String name;
    private int age;
    private String password;
    private String address;

    @Builder //롬복 사용
    public Member(String name, int age, String password, String address) {
        this.name = name;
        this.age = age;
        this.password = password;
        this.address = address;
    }
}

@Builder 엿보기

@Builder만 입력하면 어떻게 이런 마법이 일어나는 걸까요?
진짜로 빌더 패턴이 구현되었을까요?
확인 해봅시다.

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

public class Member {
    private String name;
    private int age;
    private String password;
    private String address;

    public Member(String name, int age, String password, String address) {
        this.name = name;
        this.age = age;
        this.password = password;
        this.address = address;
    }

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

    public static class MemberBuilder {
        private String name;
        private int age;

        MemberBuilder() {
        }

        public MemberBuilder name(final String name) {
            this.name = name;
            return this;
        }

        public MemberBuilder age(final int age) {
            this.age = age;
            return this;
        }

        public Member build() {
            return new Member(this.name, this.age);
        }

        public String toString() {
            return "Member.MemberBuilder(name=" + this.name + ", age=" + this.age + ")";
        }
    }
}
반응형

이제 당신은 lombok 없이는 개발하기 힘들어 졌습니다..! ㅋㅋㅋ 🤣

빌더 패턴의 장단점

장점

  • 복합 객체 생성 과정을 캡슐화 합니다.
  • 여러 단계와 다양한 절차를 거쳐 객체를 만들 수 있습니다.
    • 팩토리 메소드 패턴은 한 단계에서 모든걸 처리
  • 클래스의 내부 구조를 클라이언트로 부터 보호할 수 있습니다.

단점

  • 팩토리를 사용할 때 보다 객체를 만들 때 클라이언트에 관해 더 많이 알고 있어야 합니다.

 

 

728x90
반응형