동일한 객체를 생성하고 싶다. 새로운 인스턴스가 필요할 때 이를 언제든 복제하고 싶다. 이럴 때 어떻게 설계하는 것이 좋을까?
클라이언트가 복제 요청을 할 때, 다음과 같이 했다고 하자.
Report copyRecort(Report r){
Report returnReport = new ReportA();
}
과연 client가 파라미터 값으로 받은 Report r이 ReportA인지 알까? 알맞은 생성자를 부르는 것은 어려운 일일 것이다. 생성자 ReportA() 부분을 클라이언트는 모르게 생성, 이미 존재하는 객체로부터 clone하여 생성하고 싶다.
이럴 때 미리 prototype을 만들어 놓아, 객체를 생성하고자할 때 복제하는 방법을 프로토타입 패턴이라고 한다.
Prototype이란 미리 시제품을 만드는 것을 의미한다.
프로토타입 패턴은 새로운 객체를 생성하기 위해 이미 생성된 객체를 복제하는 패턴이다.
clone을 이용하여 복제를 하는 이유는 DB로부터 데이터를 가져오는 것은 비용이 크기 때문에 한번 접근하여 생성한 객체를 필요에 따라서 복사해 주는 것이다.
Ensemble 클래스는 여러 prototype으로 구성되어있다. Client는 이 Ensemble 클래스에 접근하여 prototype을 이용한다.
Java에서는 최상위 Object 클래스에서 인스턴스를 복제하는 clone 메소드를 만들어 제공하고 있다. Cloneable 인터페이스를 extends하여 clone() 메소드를 재정의하여 사용할 수 있다. 따라서 간편하게 복제를 할 수 있다.
product의 인터페이스를 설계하여 cloneable을 extends하였다.
public interface Product extends Cloneable{
String use(String s); //product 지원 함수
Product createClone();//재정의될 clone 함수 복제
//생성된 product를 return
}
public class PrototypeService {
//clone이 이루어질 HashMap형 product 변수 선언
private HashMap product = new HashMap<>();
//복사할 객체를 등록 name, p 파라미터 가지도록 복제
public void register(String name, Product p){
product.put(name, p);
}
//등록된 객체에서 객체를 clone
public Product create(String name){
//product를 불러와 clone 결과값을 리턴함
return ((Product) product.get(name)). createClone();
}
}
public class MessageBox implements Product{
private String deco;
public MessageBox(String deco){
this.deco = deco
}
public String use(String s){
return deco+s+deco;
}
//clone()이용한 createClone 함수 재정의
public Product createClone(){
Product p = null;
try{
//clone 메소드 이용하여 복제
p = (Product)clone();
} catch(CloneNotSupportedException ex){
ex.printStackTrace();
}
return p;
}
}