팩토리메서드를 활용한 List → DTO

2021. 7. 29. 12:03JAVA

팩토리 메서드를 사용하여 엔티티 List → DTO List로 변환하기

일단 팩토리 메서드가 모야?

  • 간단히 말하면 객체 생성을 대신 수행해주는 공장이라고 생각하면 된다.
    객체는 직접 생성하는 경우가 있고 팩토리 메서드패턴의 역할처럼 간접적으로 객체 생성 후 반환해주는 방식으로 생각해 볼 수 있다.

팩토리 메서드의 장/단점

  1. 생성 할 클래스를 미리 알지 못해도 팩토리 클래스가 객체 생성 담당
  2. 객체의 자료형이 하위 클래스에 의해서 결정 → 확장 용이성
  3. 동일한 형태로 프로그래밍 가능
  4. 확장성 있는 전체 프로젝트 구성 가능
  5. 객체가 늘어날 때 마다 하위 클래스 재정의로 인한 불필요한 많은 클래스 생성 가능성

팩토리 메서드 구조

2021-07-29-11-32-01.png

Shap.java
public interface Shape {
    void draw();
}
Circle.java
public class Circle implements Shape { 
    @Override
    public void draw() {
        System.out.println("Circle-draw() Method.");
    }
}
Rectangle.java
public class Rectangle implements Shape {
    @Override
  public void draw() {
    System.out.println("Rectangle - draw() Method.");
  }
}
ShapeFactory.java
public class ShapeFactory {
  //팩토리 메서드 - 객체 생성 후 반환
  public Shape getShape(String shapeType) {
    if (shapeType == null) {
      return null;
    } 
    if(shapeType.equalsIgnoreCase("CIRCLE")) {
      return new Circle();
    } else if (shapeType.equalsIgnoreCase("RECTANGLE")) {
      return new Rectangle();
    }
    return null;
  }
}
FactoryPatternTest.java
public class FactoryPatternTest {
  public static void main(String[] args) {
    //팩토리 클래스에서 객체를 생성 후 반환
    ShapeFactory shapeFactory = new ShapeFactory();

    Shape shape1 = shapeFactory.getShape("CIRCLE");

    //Circle 메서드 호출
    shape1.draw();

    Shape shape2 = shapeFactory.getShape("RECTANGLE");
    //Rectangle 메서드 호출
    shpae2.draw();
  }
}

원래 내가 적용했던 List → DTO 변환 코드는?

Page<DevicePacketLog> devicePacketLogs = fetchPages(size, car.getDeviceIdentity(), packetListLastId, fromDateTime, toDateTime);
List<DevicePacketLog> content = devicePacketLogs.getContent();
  • 이런식으로 Page타입의 객체를 List로 꺼내서 반복문을 돌렸다. 예를 들면

    for (int i=0; i<content.size(); i++) {
                //로그인에 따라 좋아요 판별!
                if (loginUser == null) {
                    likeCheck = false;
                } else {
                    likeCheck = heartRepository.existsByBoardIdAndUserId(boards.get(i).getId(), loginUser.getId());
                }
                boardListGetResponseDto = new BoardListGetResponseDto(boards.get(i), likeCheck, boards.get(i).getHearts().size());
                infinityScrollDto.add(boardListGetResponseDto);
            }
  • 이런식으로 코드를 작성하게 되면 읽기 힘들뿐만 아니라 성능면에서도 구리다...

Stream과 팩토리 메서드를 활용한 새로운 코드

Page<DevicePacketLog> devicePacketLogs = fetchPages(size, car.getDeviceIdentity(), packetListLastId, fromDateTime, toDateTime);
List<DevicePacketLog> content = devicePacketLogs.getContent();
List<DevicePacketLogInfiniteDTO> devicePacketLogInfiniteDTOList = new ArrayList<>();
  • 위에처럼 Page타입의 객체를 List로 뽑아내고 DTO타입의 List배열을 선언한다.
public class DevicePacketLogInfiniteDTO
{
    private Long id;
    private String deviceIdentity;
    private PacketType packetType;
    private LocalDateTime creationDateTime;

    public DevicePacketLogInfiniteDTO(DevicePacketLog devicePacketLogs) {
        this.id = devicePacketLogs.getId();
        this.deviceIdentity = devicePacketLogs.getDeviceIdentity();
        this.packetType = devicePacketLogs.getPacketType();
        this.creationDateTime = devicePacketLogs.getCreationDateTime();
    }

    //팩토리 메서드로 풀어냈다.
    public static DevicePacketLogInfiniteDTO getDTO(DevicePacketLog devicePacketLog) {
        return new DevicePacketLogInfiniteDTO(devicePacketLog);
    }
}
  • 이처럼 DTO객체에 static 메서드로 객체 생성을 해주었다.
content.stream().map(devicePacketLog1 -> DevicePacketLogInfiniteDTO.getDTO(devicePacketLog1)).forEach(devicePacketLogInfiniteDTO -> devicePacketLogInfiniteDTOList.add(devicePacketLogInfiniteDTO));
  • 그런 다음 Stream으로 변환하여 List에 담아주고 리턴하면 끝!!!

참고 사이트

'JAVA' 카테고리의 다른 글

날짜 메서드 세련되게 작성해보자!  (0) 2022.05.15
JAVA 소소한 꿀팁  (0) 2021.12.23
자바 리플렉션[Reflection] 이란??  (0) 2021.07.14