SpringBoot 공부 중에 @Builder 패턴에 대한 이해가 필요하여 @Builder 어노테이션설정으로 인하여 어떻게 동작 하는지 알아보기 위하여 정리

1. Java Builder Pattern

@Builder

public class Response {

    private Long id;
    private String name;

    public Response(Long id, String name) {
        this.id = id;
        this.name = name;
    }

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

    public static class ResponseBuilder {
        private Long id;
        private String name;

        ResponseBuilder() {}

        public ResponseBuilder id(Long id) {
            this.id = id;
            return this;
        }

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

        public Response build() {
            return new Response(id, name);
        }

        @Override
        public String toString() {
            return "ResponseBuilder{" + "id=" + id + ", name='" + name + '\'' +  '}';
        }
    }
}

2. @Builder

  • 빌더패턴을 이용했을 때 가장 큰 장점은 멤버변수의 optional과 required를 컴파일하는 시점에서 체크할 수 있다는 점
  • 특정 멤버변수에 접근하기 위한 메서드가 정해져 있기 때문에 실수로 다른 멤버변수에 다른 값을 집어넣는 실수를 막을 수 있다.
@Builder
public class Response {

    private Long id;
    private String name;

    public Response(Long id, String name) {
        this.id = id;
        this.name = name;
    }
}

3. Builder를 활용하기

import static java.lang.Thread.sleep;

public class ThreadBuilderTest {

    public static void main(String[] args) {

        ThreadOuter th = new ThreadOuter();
        th.start();
        ThreadOuter01 th01 = new ThreadOuter01();
        th01.start();

        for(int i = 11 ; i < 20 ; i++) {
            Response res = Response.builder()
                    .id(Long.valueOf(i))
                    .name("thread" + i)
                    .build();
            System.out.println(res.toString() + " :: " + Thread.currentThread().getName());
            try {
                sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

class ThreadOuter extends Thread {

    @Override
    public void run() {
        for(int i = 0 ; i < 10 ; i++) {
            Response res = Response.builder()
                    .id((long) i)
                    .name("thread01" + i)
                    .build();
            System.out.println(res.toString() + " :: " + getName());
            try {
                sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
class ThreadOuter01 extends Thread {

    @Override
    public void run() {
        for(int i = 21 ; i < 30 ; i++) {
            Response res = Response.builder()
                    .id((long) i)
                    .name("thread02" + i)
                    .build();
            System.out.println(res.toString() + " :: " + getName());
            try {
                sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

'Basic > DesignPattern' 카테고리의 다른 글

[Pattern] DTO, VO, Entity  (0) 2020.06.02

DTO

  • Value Object라고도 불리는 Transfer Object는 데이터를 전송하기 위한 객체에 대한 패턴이다.
  • 웹 개발 시 DTO, VO, Entity를 구분하는 것을 목표

DTO (Data Transfer Object)

  • DTO의 속성 및 역할

    1. 하나의 객체에 여러 타입의 값을 전달하는 일을 수행

      • 데이터 전송 객체라는 의미
    2. Transfer Object를 사용할 때 필드를 private으로 지정하여 getter() 메서드와 setter() 메서드를 만들어야 할 지, 아니면 public으로 지정하여 메서드들을 만들지 않을 지에 대한 정답은 없다.

    3. 성능상으로 따져 볼 때 getter()와 setter() 메서드를 만들지 않는 것이 더 빠르다.

      • 하지만, 정보를 은닉하고, 모든 필드의 값들을 아무나 수정할 수 없게 하려면 getter, setter 메서드를 작성하는 것이 일반적이다.
    4. getEmpName() 메서드처럼empName이 null 값이라도 null을 리턴하지 않고, 길이가 0인 String을 리턴한다.

      • 즉, TransferObject에서 잘 처리하여 각 소스에서 일일이 null 체크를 할 필요가 없기 때문에 개발에 편해진다.
    5. toString() 메서드를 해당 객체에서 구현하지 않고 호출하는 경우 알 수 없는 값을 리턴하게된다.

      • toString() 메서드를 구현하는 경우, 객체에 대한 값 비교를 명확하게 할 수 있다.
    6. Serializable의 구현 이유

      • 이 인터페이스를 구현했다고 해서 추가적으로 구현해야 하는 메서드가 있는 것은 아니다.
      • 그러나 인터페이스를 구현하는 경우 객체를 직렬화할 수가 있다.
      • 다시말해 서버 사이의 데이터 전송이 가능해진다.
      • 원격지 서버에 데이터를 전송하거나, 파일로 객체를 저장할 경우에 인터페이스를 구현해야 한다.
    7. 주로 비동기 처리를 하는 경우 사용

      • SpringBoot에서 Jackson 라이브러리의 ObjectMapper를 사용하여 Json 타입으로 변환
public class EmployeeTO implements Serializable {

    private long empId;
    private String empName;
    private String empPhone;

    public EmployeeTO() {
        super();
    }

    public EmployeeTO(long empId, String empName, String empPhone) {
        super();
        this.empId = empId;
        this.empName = empName;
        this.empPhone = empPhone;
    }

    public long getEmpId() {
        return empId;
    }

    public void setEmpId(long empId) {
        this.empId = empId;
    }

    public String getEmpName() {
        if(empName == null) return "";
        return empName;
    }

    public void setEmpName(String empName) {
        this.empName = empName;
    }

    public String getEmpPhone() {
        return empPhone;
    }

    public void setEmpPhone(String empPhone) {
        this.empPhone = empPhone;
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("empId=").append(empId);
        sb.append(" empName=").append(empName);
        sb.append(" empPhone=").append(empPhone);
        return sb.toString();
    }
}

VO (Value Object)

  • VO의 속성 및 역할
    1. 값, 객체를 의미
    2. 핵심 역할인 equals, hashCode를 오버라이딩하여 구현
      • VO 내부에 선언된 속성의 모든 값들이 VO 객체마다 값이 같아야 똑같은 객체로 판별
    3. Getter, Setter를 가질 수 있다.
      • 테이블 내에 있는 속성 외에 추가적인 속성을 가질 수 있다.
      • 여러 테이블에 대한 공통 속성을 모아 만든 BaseVO 클래스를 상속받아 사용할 수 있다.
public class EmployeeVO {

    private long empId;
    private String empName;
    private String empPhone;

    public long getEmpId() {
        return empId;
    }

    public void setEmpId(long empId) {
        this.empId = empId;
    }

    public String getEmpName() {
        return empName;
    }

    public void setEmpName(String empName) {
        this.empName = empName;
    }

    public String getEmpPhone() {
        return empPhone;
    }

    public void setEmpPhone(String empPhone) {
        this.empPhone = empPhone;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj == null || getClass() != obj.getClass()) return false;
        EmployeeVO empVo = (EmployeeVO) obj;

        return Objects.equals(empId, empVo.empId);
    }

    @Override
    public int hashCode() {
        return Objects.hash(empId);
    }
}

Entity

  • Entity
    1. DB 테이블 내에 존재하는 컬럼만을 속성 값으로 갖는 클래스
    2. Entity 클래스는 상속을 받거나 구현체여서는 안된다.
    3. 테이블 내에 존재하는 컬럼을 가져서도 안된다.
@Entity
public class EmployeeEntity {

    private long empId;
    private String empName;
    private String empPhone;

}

'Basic > DesignPattern' 카테고리의 다른 글

[Design Pattern] Builder  (0) 2020.07.05

+ Recent posts