Design Pattern

[디자인 패턴] 프로토타입 패턴 (Prototype Pattern)

꾸준함. 2024. 6. 22. 08:33

프로토타입 패턴

  • 기존 인스턴스를 복제하여 새로운 인스턴스를 만드는 방법
  • 기존 객체를 응용해서 새로운 인스턴스를 만들 때 유용
    • 특히 기존 인스턴스를 만들 때 DB 조회 혹은 API 호출 같이 비교적 시간이 오래 걸리는 작업이 선행되어야 하는 경우 유용
    • 매번 DB 조회 혹은 API 호출을 하면 시간이 오래 걸리기 때문에 이미 해당 작업을 수행해서 완성된 인스턴스를 복제한 후 일부 필드를 변경하는 방식으로 새로운 인스턴스를 만드는 방식
    • 객체 생성 비용을 줄이고, 객체 초기화 과정에서 발생하는 복잡성을 간단하게 처리 가능

 

https://www.geeksforgeeks.org/prototype-design-pattern/

 

주요 구성 요소

 

1. Prototype 인터페이스

  • 객체가 자신을 복제할 수 있도록 하는 인터페이스를 정의
  • 해당 인터페이스는 보통 clone() 메서드를 포함하며 자바에서 clone() 메서드는 protected native 메서드이기 때문에 Cloneable 인터페이스 구현체를 만들어 clone() 메서드를 재정의해야 함

 

* clone() 메서드 관련해서는 이펙티브 자바 아이템 13에서 다루었으므로 해당 게시글 참고하는 것을 권장드립니다.

 

2. Concrete Prototype

  • 프로토타입 인터페이스를 구현한 실제 객체
  • 해당 객체는 자시니의 복사본을 반환할 수 있어야 함

 

3. Client

  • 새로운 객체를 생성할 때 직접 객체를 생성하는 대신 프로토타입 객체의 clone() 메서드를 호출하여 객체를 생성

 

프로토타입 구현 예시

 

1. Prototype 인터페이스 정의


public interface Prototype extends Cloneable {
}
view raw .java hosted with ❤ by GitHub

 

2. ConcretePrototype 정의

  • ConcretePrototype을 생성하는데 5초가 걸린다고 가정

 

@Setter
@ToString
public class ConcretePrototype implements Prototype {
private String field;
public ConcretePrototype(String field) throws InterruptedException {
Thread.sleep(5000); // 생성 비용이 비싸 5초 걸린다고 가정
this.field = field;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
view raw .java hosted with ❤ by GitHub

 

3. Client 코드 예시

 

public class Client {
public static void main(String[] args) throws CloneNotSupportedException, InterruptedException {
long start = System.nanoTime();
ConcretePrototype prototype = new ConcretePrototype("original");
long end = System.nanoTime();
long duration = end - start;
System.out.println(String.format("prototype: %s, 생성 시간: %s나노초", prototype, duration));
start = System.nanoTime();
ConcretePrototype cloned = (ConcretePrototype) prototype.clone();
cloned.setField("cloned");
end = System.nanoTime();
duration = end - start;
System.out.println(String.format("cloned: %s, 생성 시간: %s나노초", cloned, duration));
}
}
view raw .java hosted with ❤ by GitHub

 

부연 설명

  • 처음 생성한 인스턴스는 5초가 넘게 걸리지만
  • 프로토타입 패턴을 적용한 cloned는 clone() 메서드를 호출하여 기존 인스턴스를 복제했으므로 1초도 안 걸리는 것을 확인 가능

 

프로토타입 패턴 장단점

 

장점

  • 기존 인스턴스를 복제하는 방식이므로 복잡한 객체를 생성하는 과정을 은닉할 수 있음
  • 기존 객체를 복제하는 고자어이 새 인스턴스를 생성하는 것보다 비용적인 면에서 효율적
  • 추상적인 타입을 반환할 수 있음

 

단점

  • 복제한 객체를 만드는 과정 자체가 복잡할 수 있음
    • clone()은 기본적으로 얕은 복사를 지원하기 때문에 컴포지션을 이용한 객체의 경우 clone() 메서드를 재정의할 때 깊은 복사를 직접 구현해야 함
    • 특히 객체 간 순환참조가 있는 경우 clone() 메서드 재정의하기가 상당히 까다로워질 수 있음

 

실무에서 쓰이는 프로토타입 패턴

 

1. ArrayList 생성자

  • ArrayList는 Cloneable을 상속하기 때문에 clone() 메서드를 지원함
    • 하지만 코드 상에서는 확장성을 위해 추상화된 인터페이스인 List 변수에 ArrayList를 저장
    • List는 Cloneable을 상속하지 않았기 때문에 clone()을 지원 X

 

  • ArrayList 생성자에 파라미터로 컬렉션을 넘겨주면 프로토타입 패턴 효과를 얻을 수 있음
    • 엄밀히 말하면 프로토타입 패턴은 아니지만 비슷한 효과


public static void main(String[] args) {
Student jaimemin = new Student("jaimemin");
Student gudetama = new Student("gudetama");
// ArrayList<Student> students = new ArrayList<>();
// ArrayList<Student> clonedStudents = (ArrayList<Student>)students.clone();
List<Student> students = new ArrayList<>();
students.add(jaimemin);
students.add(gudetama);
List<Student> clone = new ArrayList<>(students);
System.out.println(clone);
}
view raw .java hosted with ❤ by GitHub

 

2. ModelMapper

  • 자바 객체 간의 매핑을 간편하게 해주는 라이브러리이며 내부적으로 리플렉션을 이용
  • 주로 DTO(Data Transfer Object)와 엔티티(Entity) 간의 변환 작업에서 사용
    • 코드의 중복을 줄이고, 객체 변환의 복잡성을 줄일 수 있음


@Data
public class UserEntity {
private Long id;
private String username;
private String email;
}
@Data
public class UserDto {
private String username;
private String email;
}
public class ModelMapperExample {
public static void main(String[] args) {
ModelMapper modelMapper = new ModelMapper();
UserEntity userEntity = new UserEntity();
userEntity.setId(1L);
userEntity.setUsername("jaimemin");
userEntity.setEmail("example@example.com");
UserDto userDTO = modelMapper.map(userEntity, UserDto.class);
System.out.println(userDTO);
}
}
view raw .java hosted with ❤ by GitHub

 

참고

코딩으로 학습하는 GoF의 디자인 패턴 - 백기선 강사님

반응형