Pattern - Prototype
성공은 형편없는 선생님이다. 그것은 똑똑한 사람들로 하여금 절대 패할 수 없다고 착각하게 만든다.
- 빌게이츠 ( 마이크로소프트 공동 창업자 )
의도
객체 생성과 관련된 패턴들은 일부 영역이 겹치는 부분들이 있는데, 프로트 타입 패턴은 주로 다른 객체 생성 패턴들과 많이 같이 사용될 수 있습니다. 추상 팩토리 패턴이 프로토타입들의 집합을 갖고 있다가, 클론(clone)한 프로덕트 객체를 반환할 수 있습니다. 일반화 관계로 표현을 할 때, 파생 클래스의 개수가 과도히 많아지고 각 클래스의 메서드가 수행하는 알고리즘에서 차이가 없고 생성 시에 개체의 속성에 차이만 있다면 원형 패턴을 사용하는 것이 효과적입니다.
활용성
Object 생성이 높은 비용으로 수 많은 요청을 하는 경우, 또는 비슷한 Object 를 지속적으로 생성해내야 할 때 유용하게 사용할 수 있다.
- 관련 패턴
- 이번 장의 끝에서 잠깐 언급했듯이 원형 패턴과 추상 팩토리 패턴은 어떤 면에서는 경쟁적인 관계입니다. 하지만 함께 사용될 수도 있습니다.
- 추상 팩토리 패턴은 원형 집합을 저장하다가 필요할 때 복제하여 제품 객체를 반환하도록 사용할 수 도 있습니다.
코드 예제 - 기본
package DesignPattern.gof_prototype;
public class Battle {
public static void main(String[] args) {
Unit prove1 = Nexus.createProve();
prove1.Harvest();
prove1.Harvest();
prove1.Harvest();
Arbiter arbiter1 = new Arbiter();
Unit prove2 = arbiter1.copyRealUnit(prove1);
System.out.println("prove 1 == prove 2 의 결과 : " + (prove1 == prove2) );
System.out.println(prove1.getMineralCapacity());
System.out.println(prove2.getMineralCapacity());
}
}
- 컴파일 결과
코드 예제 - Deep Copy / Shallow Copy
package DesignPattern.gof_prototype;
public interface Unit{
public void Harvest();
public void Attack();
public void Building();
public Unit CloneUnitOrNull();
public int getMineralCapacity();
}
package DesignPattern.gof_prototype;
public class Probe implements Unit{
private int mineralCapacity = 0;
public void Harvest(){
System.out.println("자원을 캡니다.");
mineralCapacity += 1;
}
public void Attack(){
System.out.println("공격을 합니다.");
}
public void Building(){
System.out.println("건물을 짓습니다.");
}
public int getMineralCapacity(){
return mineralCapacity;
}
private void setCapacity(int capacity){
this.mineralCapacity = capacity;
}
public Unit CloneUnitOrNull(){
try {
Object cloneObject = clone();
return (Unit)cloneObject;
}catch (CloneNotSupportedException e){
e.printStackTrace();
return null;
}
}
@Override
public Object clone() throws CloneNotSupportedException{
Probe probe = new Probe();
probe.setCapacity(mineralCapacity);
return probe;
}
}
package DesignPattern.gof_prototype;
public class Nexus {
public static Unit createProve(){
return new Probe();
}
}
package DesignPattern.gof_prototype;
public class Arbiter {
public Unit copyRealUnit(Unit unit){
return unit.CloneUnitOrNull();
}
}
코드 예제 - Clonable 의 Clone을 이용할 경우
package DesignPattern.gof_prototype.sample002;
import java.util.List;
public class ComplexProcess implements Cloneable {
private final Process complexProcess;
public ComplexProcess(Process complexProcess){
this.complexProcess = complexProcess;
}
public List<Object> getProcessResult(){
return complexProcess.getResultOfComplexProcess();
}
public ComplexProcess getCloneProcess() throws CloneNotSupportedException {
return (ComplexProcess)super.clone();
}
}
package DesignPattern.gof_prototype.sample002;
import java.util.ArrayList;
import java.util.List;
public class CopyAthousandRowsProcess implements Process {
public List<Object> getResultOfComplexProcess() {
return new ArrayList<>();
}
}
package DesignPattern.gof_prototype.sample002;
import java.util.List;
public interface Process {
public List<Object> getResultOfComplexProcess();
}
package DesignPattern.gof_prototype.sample002;
public class Processor {
public static void main(String[] args) throws CloneNotSupportedException {
ComplexProcess complexProcess1 = new ComplexProcess(new CopyAthousandRowsProcess());
complexProcess1.getProcessResult();
ComplexProcess complexProcess2 = complexProcess1.getCloneProcess();
complexProcess2.getProcessResult();
System.out.println("complexProcess1 == complexProcess1 의 결과는 " + (complexProcess1 == complexProcess2));
}
}