Prototype Pattern은 클래스로부터 인스턴스를 생성하는 것이 아니라, 인스턴스로부터 인스턴스를 생성하게 된다
(Specify the kind of objects to create using a prototypical instance, and create new objects by copying this prototype)
- ConcretePrototype 클래스에서 복사본을 생성할 때 단순 복사본(Shallow Copy)을 생성한다는 것을 알 수 있다. 닷넷에서는 단순 복사본을 생성하는 메서드 MemberwiseClone()이 제공된다. Java는 Clone()이 제공된다.
- 단순 복사본(Shallow Copy)은 원본의 참조를 유지하지만 전체 복사본(Deep Copy)은 원본의 참조를 유지하지 않고 참조되는 객체의 새로운 복사본을 참조한다.
객체 X가 객체 A, B를 참조하고, 객체 A는 객체 M을 참조한다고 할 때 X에 대한 단순 복사본 Y는 객체 A와 B를 참조한다.Deep Copy는 new()해서 생성된 것이라 생각하면 쉬울 것 같다.
- 활용성 ==> 인스턴스화할 클래스를 런타임에 지정할 때, 클래스의 인스턴스들이 서로 다른 상태 조합 중에 어느 하나일 때
- 관련 패턴 ==> 추상 팩토리 패턴과는 어떤 면에서 경쟁적인 관계이다. 하지만 함께 사용될 수도 있다. 추상 팩토리 패턴은 원형 집합을 저장하다가 필요할 때 복제하여 제품 객체를 반환하도록 사용할 수도 있다. 복합체 패턴과 장식자 패턴을 많이 사용해야 하는 설계에서 원형 패턴을 사용해서 재미를 볼수도 있다.
public abstract class AColorBase implements Cloneable {
public abstract AColorBase createClone();
--------------------------------------------------------------
public class Color extends AColorBase {
private int red;
private int green;
private int blue;
public Color(int red, int green, int blue) {
this.red = red;
this.green = green;
this.blue = blue;
}
public AColorBase createClone() {
AColorBase aColorBase = null;
try {
aColorBase =(AColorBase)this.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return aColorBase;
}
public String toString() {
return String.format("red[%d], green[%d], blue[%d]", this.red, this.green, this.blue);
}
Getter/ Setter …
--------------------------------------------------------------
public class ColorManager {
private Hashtable<String, AColorBase> colorTable;
public ColorManager() {
colorTable = new Hashtable<String, AColorBase>();
}
public AColorBase register(String colorName, AColorBase colorBase) {
return colorTable.put(colorName, colorBase);
}
public AColorBase create(String colorName) {
return colorTable.get(colorName).createClone();
}
--------------------------------------------------------------
public class Client {
public static void main(String[] args) {
// 인스턴스 만들기
Color green = new Color(0, 200, 0);
ColorManager colorManager = new ColorManager();
colorManager.register("red", new Color(200, 0, 0));
colorManager.register("green", green);
colorManager.register("blue", new Color(0, 0, 200));
// 외부:인스턴스 만들기, 내부:인스턴스 복사
// 복사(clone)되기 때문에 생성의 부하가 적음
AColorBase newColor = colorManager.create("red");
System.out.println(newColor);
newColor = colorManager.create("green");
System.out.println(newColor);
--------------------------------------------------------------
red[200], green[0], blue[0]
red[0], green[200], blue[0]
- 구현 관련
- 위의 구현형태는 하나의 클래스로부터 상태값이 다른 여러 객체를 생성하고, 생성된 객체들을 복사해서 사용하는 형태이다. 이와 다르게 AColorBase와 같은 Prototype 클래스을 구현하는 여러개의 클래스들의 객체를 각각 생성하고 생성된 객체들을 복사해서 사용해도 된다. 상황에 따라서 적절히 선택해서 구현하면 된다.
- ColorManager와 같은 Prototype Manager 객체는 register(생성), unRegister(제거), check(확인)와 같은 메소드들을 일반적으로 제공한다.
- 그림판의 왼쪽에 있는 palette가 ColorManager와 비슷한 형태이고, palette에서 선택한 도형을 그림판에서 생성할때 마다 clone 되어 생성되는 형태이다. 사용자에 의해 실시간으로 도형을 생성하기 위해서는 palette와 같은 형태의 class가 있어야 한다. 예를 들면 사용자에 의해 선택된 2가지의 도형을 합친 새로운 도형을 만들고자 하면 palette에 두가지 도형에 대해 composite pattern을 사용해서 등록하고 사용하면 된다.
- 참고