**프로토타입 패턴**은 소프트웨어 디자인 패턴 용어로, 생성할 객체들의 타입이 프로토타입인 인스턴스로부터 결정되도록 하며, 인스턴스는 새 객체를 만들기 위해 자신을 복제(clone)하게 된다.

패턴을 구현하려면, 우선  메소드 내의 코드를 구현한다.

## 원칙
객체 생성과 관련된 패턴들은 서로 영역이 겹치는 면이 있다. 프로토타입 패턴과 추상 팩토리 패턴 중 어느 하나가 적용될 수 있는 경우가 있다. 추상 팩토리 패턴이 프로토타입들의 집합을 갖고있다가, 클론(clone)한 뒤 프로덕트(product) 객체를 반환할 수도 있다.

다시 말해 추상 팩토리 클래스는 종종 팩토리 메소드와 함께 구현하거나

보통 설계는 처음에는 팩토리 메소드로 출발한다. 다음에 설계자의 재량에 따라 추상 팩토리 패턴, 빌더 패턴, 프로토타입 패턴으로 바뀔 수 있다.

프로토타입은 서브클래싱을 필요로 하지 않는다. 하지만 "초기화" 동작을 필요로 한다. 팩토리 메서드 패턴은 서브클래싱을 필요로 하나, "초기화" 동작은 필요로 하지 않는다.

설계자는 컴포지트 패턴이나 데코레이터 패턴을 매우 많이 사용한 무거운 설계를 프로토타입을 사용하여 더 좋게 만들 수 있다.

원칙은 "런타임"에 또 다른 "객체"를 생성한다는 것이다. 다시 말해 이 시점에 가서 클로닝(cloning)을 하는 객체의 "실제 복사본"이 만들어지는 것이다. "실제 복사본"이라는 말은 새로 생성되는 객체가 클로닝(cloning) 당하는 객체의 애트리뷰트와 똑같은 애트리뷰트를 가질 것이라는 말이다. 반면에, ""를 이용해 객체를 생성했다면, 새로이 생성된 객체의 애트리뷰트들은 초기값을 가질 것이다.

예를 들면, 은행 계좌 입출금 트랜잭션을 수행하는 시스템을 가정해 보자. 프로그래머는 은행 이용자의 계좌 정보를 갖고 있는 객체를 하나 복사한다. 그 객체를 가지고 그 객체 상에다 은행 입출금 트랜잭션을 수행한다. 그 다음 원래의 객체를 이 객체로 바꿔치기한다. 프로그래머는 이런 경우 을 쓴다.

## 예제

### C++
using namespace std;

enum RECORD_TYPE_en
 CAR,
 BIKE,
 PERSON

/**

class Record
 public :

 Record {}

 virtual ~Record {}

 virtual Record* Clone const=0;

 virtual void Print const=0;

/**

class CarRecord: public Record
 private :
 string m_oStrCarName;

 uint32_t m_ui32ID;

 public :

 CarRecord
 m_ui32ID(_ui32ID)

 CarRecord(const CarRecord& _oCarRecord)
 m_oStrCarName = _oCarRecord.m_oStrCarName;
 m_ui32ID = _oCarRecord.m_ui32ID;

 ~CarRecord {}

 CarRecord* Clone const
 return new CarRecord(*this);

 void Print const
 cout << "Car Record" << endl
 << "Name : " << m_oStrCarName << endl
 << "Number: " << m_ui32ID << endl << endl;

/**

class BikeRecord: public Record
 private :
 string m_oStrBikeName;

 uint32_t m_ui32ID;

 public :
 BikeRecord
 m_ui32ID(_ui32ID)

 BikeRecord(const BikeRecord& _oBikeRecord)
 m_oStrBikeName = _oBikeRecord.m_oStrBikeName;
 m_ui32ID = _oBikeRecord.m_ui32ID;

 ~BikeRecord {}

 BikeRecord* Clone const
 return new BikeRecord(*this);

 void Print const
 cout << "Bike Record" << endl
 << "Name : " << m_oStrBikeName << endl
 << "Number: " << m_ui32ID << endl << endl;

/**

class PersonRecord: public Record
 private :
 string m_oStrPersonName;

 uint32_t m_ui32Age;

 public :
 PersonRecord
 m_ui32Age(_ui32Age)

 PersonRecord(const PersonRecord& _oPersonRecord)
 m_oStrPersonName = _oPersonRecord.m_oStrPersonName;
 m_ui32Age = _oPersonRecord.m_ui32Age;

 ~PersonRecord {}

 Record* Clone const
 return new PersonRecord(*this);

 void Print const
 cout << "Person Record" << endl
 << "Name: " << m_oStrPersonName << endl
 << "Age : " << m_ui32Age << endl << endl ;

/**

class RecordFactory
 private :
 map m_oMapRecordReference;

 public :
 RecordFactory
 m_oMapRecordReference[CAR] = new CarRecord;
 m_oMapRecordReference[BIKE] = new BikeRecord;
 m_oMapRecordReference[PERSON] = new PersonRecord;

 ~RecordFactory
 delete m_oMapRecordReference[CAR];
 delete m_oMapRecordReference[BIKE];
 delete m_oMapRecordReference[PERSON];

 Record* CreateRecord(RECORD_TYPE_en enType)
 return m_oMapRecordReference[enType]->Clone;

int main
 RecordFactory* poRecordFactory = new RecordFactory;

 Record* poRecord;
 poRecord = poRecordFactory->CreateRecord(CAR);
 poRecord->Print;
 delete poRecord;

 poRecord = poRecordFactory->CreateRecord(BIKE);
 poRecord->Print;
 delete poRecord;

 poRecord = poRecordFactory->CreateRecord(PERSON);
 poRecord->Print;
 delete poRecord;

 delete poRecordFactory;
 return 0;

### C#
public enum RecordType
 Car,
 Person

/// 
public abstract class Record
 public abstract Record Clone;

/// 
public class PersonRecord: Record
 string name;
 int age;

 public override Record Clone
 return (Record)this.MemberwiseClone; // default shallow copy

/// 
public class CarRecord: Record
 string carname;
 Guid id;

 public override Record Clone
 CarRecord clone = (Record)this.MemberwiseClone; // default shallow copy
 clone.id = Guid.NewGuid; // always generate new id
 return clone;

/// 
public class RecordFactory
 private static Dictionary _prototypes =
 new Dictionary;

 /// 
 public RecordFactory
 _prototypes.Add;
 _prototypes.Add;

 /// 
 public Record CreateRecord(RecordType type)
 return _prototypes[type].Clone;

### PHP
PHP 5에서는, 객체는 레퍼런스 형태로 전달된다(pass by reference).

값 형태로 전달하기 위해서는, "매직 펑션" __clone을 써야한다.
이러한 까닭으로 PHP 5에서는 프로토타입 패턴을 구현하기 매우 쉽다.

<?php
abstract class BookPrototype {
 protected $title;
 protected $topic;
 abstract function __clone;
 function getTitle {
 return $this->title;
 function setTitle($titleIn) {
 $this->title = $titleIn;
 function getTopic {
 return $this->topic;

class PHPBookPrototype extends BookPrototype {
 function __construct {
 $this->topic = 'PHP';
 function __clone {

class SQLBookPrototype extends BookPrototype {
 function __construct {
 $this->topic = 'SQL';
 function __clone {

 writeln('BEGIN TESTING PROTOTYPE PATTERN');
 writeln('');

 $phpProto = new PHPBookPrototype;
 $sqlProto = new SQLBookPrototype;

 $book1 = clone $sqlProto;
 $book1->setTitle('SQL For Cats');
 writeln('Book 1 topic: '.$book1->getTopic);
 writeln('Book 1 title: '.$book1->getTitle);
 writeln('');

 $book2 = clone $phpProto;
 $book2->setTitle('OReilly Learning PHP 5');
 writeln('Book 2 topic: '.$book2->getTopic);
 writeln('Book 2 title: '.$book2->getTitle);
 writeln('');

 $book3 = clone $sqlProto;
 $book3->setTitle('OReilly Learning SQL');
 writeln('Book 3 topic: '.$book3->getTopic);
 writeln('Book 3 title: '.$book3->getTitle);
 writeln('');

 writeln('END TESTING PROTOTYPE PATTERN');

 function writeln($line_in) {
 echo $line_in."";
?>

출력은 다음과 같다.