우리가 코딩할때 stack overflow나 블로그를 뒤져가면서 관련 코드를 찾고, 그대로 따라서 타이핑 해도 되지만, 바로 복사해서 쓰듯(ㅋㅋ), 객체의 생성때마다 매번 재생성 하고 관련 파라미터를 세팅해주는 것이 아니라, 이미 세팅된 애를 복사해서 사용할때 유용하다.
이미 세팅된 애를 복사해서 쓰기 때문에, 객체 생성과정이 매우 복잡 or 비용이 크다면 ( DB 에서 참조, File I/O 등 ) 해당 비용을 줄일 수 있다!
또, 팩토리 패턴처럼 별도의 creator를 만들지 않아도 되니 서브클래스 숫자가 줄어드는 장점도 있다.
여러분은 npc를 만들고 배치 시키는 기능을 지원하기 위한 사전 작업을 하기로 했다.
오픈월드 게임을 해본 분들은 아시겠지만, 메쉬만 다르고 똑같은 액션 똑같은 행동들을 하는 npc들이 즐비해있다. 실제 게임을 만들때 그러한 npc들을 여기저기 배치해둘 것이다. (안그럼 밋밋해보이고, 모든 npc를 개성있게 만들기에는 시간이 부족하며 가성비가 안나온다...)
clone 메소드를 override하여 각 종류의 npc 인스턴스를 만든뒤 대입 연산자를 통해 copy 한다.
(인스턴스의 copy를 shallow copy로 할지 deep copy로 할지는 요구사항에 따라 결정하여 구현한다.)
이제 npc들의 '원형'들을 만들어 store에 등록해두자!
(예제라 코드로 하지만, 실제 엔진이라면 툴 차원에서 지원할 것이다.)
NPCStore* store = NPCStore::This();
//1) speed가 빠른 행인 npc
NPC* npc = new WalkerNPC(200);
store->addNPCPrototype("Fast_NPC", npc);
//2) speed가 느린 행인 npc
npc = new WalkerNPC(10);
store->addNPCPrototype("Slow_NPC", npc);
//3) hp가 높은 고정 npc
npc = new FixedNPC(100000);
store->addNPCPrototype("High_Hp_NPC", npc);
//4) hp가 낮은 고정 npc
npc = new FixedNPC(20);
store->addNPCPrototype("Low_Hp_NPC", npc);
이처럼 store 같은 'manager'가 있으면 같은 class의 인스턴스라도 다른 state( WalkerNPC의 speed, FixedNPC의 hp)를
가지는 새로운 원형으로 등록시키는게 가능하다!
NPC* clonedNPC;
//1) speed가 느린 행인 npc
clonedNPC = store->getNPC("Slow_NPC");
clonedNPC->info();
//2) hp가 높은 고정 npc
clonedNPC = store->getNPC("High_Hp_NPC");
clonedNPC->info();
스토어로부터 새로운 npc 인스턴스를 얻었으니 배치할 수 있다!
이처럼 유용한 패턴이지만 역시 단점도 있다.
바로 clone() 메소드이다.
clone() 메소드를 반드시 구현해야 하는데, 다음과 같은 3가지 사항에서 clone() 메소드 구현이 어려울 수 있다.
1. 이미 존재하는 class를 prototype으로 만드려 할때 어려울 수 있다.
2. 언어적으로 '복사'를 지원하지 않는다.
3. 환형참조가 있는 object
또한, concrete class에서만 아주 특별하게 쓰는 field( member variable )가 있고, 이 field를 외부에서
참조해야 하는경우 결국 down cast가 발생한다.
(근데 이건 subclass를 은닉시키는 모든 상황에서 발생가능한 것이므로, 그러한 상황이 나오지 않게