프로토타입(Prototype) 패턴: 생성패턴
원본 객체를 새로운 객체에 복사하여 필요에 따라 수정하는 메커니즘을 제공한다.
프로토타입패턴은 객체를 생성하는데 비용(시간, 자원)이 많이 들고, 비슷한 객체가 이미 있는 경우에 사용되는 생성 패턴 중 하나이다.
보통 DB에서 데이터를 읽어와 인스턴스를 생성할 때나 요청을 보내서 가져온 데이터로 인스턴스를 만들어야 하는 경우 오래시간과 큰 리소스가 필요하다. 때문에 데이터를 복제해서 새로운 인스턴스를 만들고 원하는 값만 일부 변경하여 사용한다.
프로토타입패턴은 복사를 위해 자바에서 제공하는 clone메소드를 사용할 수 있다.
자바에서 제공하는 clone메소드를 사용하기 때문에 생성하고자 하는 객체에 clone에 대한 Override를 요구한다. 이때, 주의할 점은 반드시 생성하고자 하는 객체의 클래스에서 clone메소드가 정의되어있어야한다.
프로토타입 패턴의 장단점
장점
- 복잡한 객체를 만드는 과정을 숨길 수 있다.
- 기존 객체를 복제하는 과정이 새 인스턴스를 만드는 것보다 비용(시간 또는 메모리)적인 면에서 효율적일 수 있다.
- 추상적인 타입을 리턴할 수 있다.
단점
- 복잡한 객체를 만드는 과정 자체가 복잡할 수 있다. (특히 순환 참조가 있는 경우)
ModelMapper
서로 다른 클래스의 값을 한 번에 복사하게 도와주는 라이브러리로,어떤 Object (Source Object) 에 있는 필드 값들을 자동으로 원하는 Object (Destination Object) 에 매핑 시켜주는 라이브러리다.
implementation 'org.modelmapper:modelmapper:2.4.2'
자바에서 제공해주는 clone()은 문제점이 많기 때문에 자바 프로젝트를 다룬다면 의존성을 추가해서 ModelMapper 라이브러리를 사용하는 것이 더 효율적이라는 얘기가 많다. 명확한 프로토타입 패턴이라 말할 수는 없지만, 비슷한 역할을 하기에 ModelMapper 라이브러리를 사용할 수 있다.
프로토타입 패턴의 예시
Player
import lombok.Getter;
import lombok.Setter;
@Setter @Getter
public class Player implements Cloneable{
private String name;
private int HP;
private int MP;
private Weapon weapon;
@Override
public Player clone() throws CloneNotSupportedException{
// 아래와 같이 기존 메서드를 활용하면, 필드로 선언된 인스턴스가 얕은 복사가 되어, 원본객체에 영향을 미친다.
//return (Player) super.clone();
Weapon weapon = new Weapon(this.weapon.getName());
Player player = new Player();
player.setName(this.name);
player.setHP(this.HP);
player.setMP(this.MP);
player.setWeapon(weapon);
return player;
}
}
* colne() 메서드를 그대로 쓰면 얕은 복사가 된다. 때문에 주석처리가 된 방식으로 clone하는 것은 바람직하지 않다.
* setter은 되도록 지양해야한다. 무분별한 setter 사용은 이 데이터가 왜 변경되는지 알 수 없기 때문에 의미있는 메서드 이름으로 사용해야한다. 하지만 나는 test니까 그냥 썼음...주저리주저ㅏ리...
Weapon
import lombok.Getter;
import lombok.Setter;
@Setter @Getter
public class Weapon {
private String name;
Weapon(String name){
this.name = name;
}
}
Client
public class Client {
public static void main(String[] args) throws CloneNotSupportedException{
Player player = new Player();
player.setName("안녕");
player.setHP(50);
player.setMP(100);
player.setWeapon(new Weapon("금빛칼"));
Player clone = player.clone();
clone.setName("닉넴을바꿀게");
clone.getWeapon().setName("양날도끼");
System.out.println(player.getName() + " " + clone.getName());
}
}
Reference
'OOP > Design Pattern' 카테고리의 다른 글
07. 어댑터(Adapter) 패턴 (0) | 2023.02.14 |
---|---|
06. 싱글톤(Singleton)패턴 (0) | 2023.02.13 |
04. 빌더(Builder) 패턴 (0) | 2023.02.13 |
03. 추상 팩토리(Abstract Method) 패턴 (0) | 2023.02.13 |
02. 팩토리 메서드(Factory Method) 패턴 (0) | 2023.02.13 |