

프로토 타입 패턴은 이미 만들어진 객체(프로토타입)을 복제해서 새로운 객체를 생성하는 디자인 패턴이에요. 보통 new 키워드로 바로 생성자 호출을 통해 객체를 생성해요. 하지만 객체 생성 과정이 복잡하거나 비용이 크면, 이미 준비된 객체를 복사해서 쓰는게 훨씬 효율적일 거에요.(clone 메서드로 많이 써요) 그래서 객체 생성 비용을 줄이고, 그 생성 로직을 캡슐화하기 위해서 프로토타입 패턴을 활용해요.
프로토타입 패턴은 보통 Prototype, ConcretePrototype, Registry로 구성되요 . Prototype은 clone 메서드를 가진 인터페이스이구요. ConcretePrototype은 Prototype 구현체에요. Registry는 없어도 되지만, Prototype 생성을 관리하기 위해 함께 사용해요.

Prototype
역할: 객체 복제를 위한 공통 인터페이스를 제공해요.
특징:
보통 clone 메서드를 가져요.
Client는 이 인터페이스에 의존해요.
ConcretePrototype
역할: 실제 복제될 객체에요.
특징:
자신의 상태를 복사해서 새로운 객체를 생성해요.
얕은 복사/깊은 복사같은 알고리즘을 직접 조절해요.
Register
역할: 프로토타입을 id로 관리하고 등록하는 저장소
특징:
clone 메서드조차 사용하지 않도록 여러 종류의 객체 생성을 위임받아 캡슐화해요.
새로운 prototype도 쉽게 추가하여 동적으로 사용할 수 있어요.
게임에서 몬스터를 생성하는 기능을 프로토타입 패턴으로 만들어 볼게요.
기능
일반 몬스터와 이벤트 몬스터를 쉽게 만들 수 있다.
일반 몬스터는 피가 100%이지만, 이벤트 몬스터는 피가 50%인 상태로 생성된다.
Prototype(몬스터 인터페이스) | ConcretePrototype(몬스터 구현체) | Register |
|---|---|---|
| | |
Client | ||
| ||
위 코드는 Monster 인터페이스, ConcreteMonster (Common, Event Monster), Register(몬스터 등록 및 생성기)로 만들어진 코드에요. 클라이언트 입장에서는 깔끔하게 다양한 몬스터 생성과 등록이 가능한 코드가 만들어져요. 물론 위 코드에 대해서 별로 좋지 않은 코드라고 할 수 있을 것 같아요. 왜냐하면 생각에 따라 Normal 몬스터와 Event 몬스터 생성 과정을 다르게 설계할 수 있기 때문이에요. 당장 저에게 생각나는 방식도 3가지가 있어요.
Register를 Common Register와 EventRegister로 분리해서 설계하기. [Registry의 분리]
Registry 수가 많아지지만, Prototype 활용도가 떨어짐.(하지만 확실히 이벤트와 일반 생성의 분리)
Common Monster 클론 후 수치 변형도록 SubClass로 Event Monster 설계. [기존 Common Monster의 재사용 및 상속]
Prototype 활용도가 높아지지만, 생성 로직이 복잡해질 수 있음.
Common Monster 생성 후 직접 HP를 반으로 깎기
구현 난이도는 낫지만, 이벤트 규칙이 곳곳에 흩어질 위험성이 큼.
각각 확실한 장단점이 더 있을 거라고 생각해요. 상황에 맞게 뭐가 더 나을지 판단해서 사용하면 될거에요. 아마 이걸 읽는 여러분들은 훨씬 잘하실 것 같아요.
장점
객체 생성 비용을 줄일 수 있어요. (연산같은 복작합 과정 없이 기존 값 그대로 사용)
복잡한 객체들에 대한 사전 설정도 상속 대신 프로토타입 방식을 활용할 수 있어요.
런타임에 객체 생성 방식을 유연하게 변경할 수 있어요.
단점
깊은 복사가 필요한 경우 구현이 어려울 수 있어요.
순환 참조가 있는 객체는 복제가 어려워요.
복사 메서드를 항상 구현해줘야해요.
프로토타입 패턴과 팩토리 패턴은 모두 생성 패턴의 한 종류에요. 하지만 그 목적이 달라요. 프로토타입 패턴은 객체 생성의 비용을 줄이는 것이 주된 목적이고, 팩토리 패턴은 객체 생성 과정의 복잡도를 줄이기 위해 사용해요. 그리고 꼭 1가지만 골라서 사용하진 않아요. 추상 팩토리 메서드가 있으면, 그 구상 팩토리의 생성을 프로토타입 패턴을 통해 생성하는 것이 그 한 가지 예시에요.
구분 | 프로토타입 | 팩토리 |
|---|---|---|
객체 생성 방식 | 기존 객체 복제 | 새 객체 생성 |
생성 비용 | 낮음 | 상대적으로 높음 |
생성 로직 | 객체 내부에 존재 | 팩토리 클래스에 존재 |
런타임 유연성 | 높음 | 보통 |
프로토타입 패턴은 "어떻게" 만들지 보다 "복사"에 초점이 맞춰진 패턴이에요. 객체 생성 비용이 크고 로직이 복잡할수록 이 패턴의 필요성이 커져요. 다음 글에서는 비지터 패턴을 글로 쓸게요. 비지터 패턴이 HeadFirst 디자인 패턴의 진짜 마지막 패턴이겠네요. 정말 힘든 여정인거 같아요!