프로토타입(Prototypical) 패턴

2024. 3. 18. 17:38디자인패턴

프로토 타입 패턴 : 원형이 되는 인스턴스를 사용하여 생성할 객체의 종류를 명시하고 이렇게 만든 견본을 복사해서 새로운 객체를 생성합니다.

 

 

한 가지 스포너는 한 가지 몬스터 인스턴스만 만든다고 예를 들면 다음과 같은 클래스 상속 구조를 따르게 된다.

이러한 상속구조를 코드로 그대로 옮기게 된다면 코드의 중복성이 높기 때문에 비 효율적이다.

이러한 구조에서 프로토 타입 패턴으로 해결 할 수 있는 방법이 있다.

 

핵심은 어떤 객체가 자기가 비슷한 객체를 스폰 할 수 있다는 점이다

 

이를 구현하기 위해 Monster 클래스에 추상 메서드 clone()을 추가하는 과정이다.

 

 

1
2
3
4
5
6
class Monster
{
public:
    virtual void ~Monster();
    virtual Monster* clone() = 0;
};
cs

Monster 하위 클래스에 자신과 자료형과 상태가 같은 새로운 객체를 반환하도록 clone() 을 구현한다.

 

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Ghost :public Monster
{
public:
    Ghost(int health, int speed) : health_(health), speed_(speed) {}
 
    virtual Monster* Clone()
    {
        return new Ghost(health_, speed_);
    }
 
private:
    int health_;
    int speed_;
};
cs

 

Monster를 상속받는 모든 클래스에 clone 메서드가 있다면 스포널 클래스를 종류별로 만들 필요 없이 하나만

만들면 된다.

 

 

1
2
3
4
5
6
7
8
9
10
11
class Spawner
{
public:
    Spawner(Monster* propotype) : prototype_(propotype) { }
    Monster* SpawnMonster()
    {
        return prototype_ -> clone();
    }
private:
    Monster* prototype_;
};
cs

 

스포너 클래스 안에는 Monster Type의 프로토타입 변수가 있다. Monster를 상속받는 모든 클래스들은

clone() 메서드가 있고 이 스포너 클래스 하나만 있으면 모든 종류의 Monster 타입을 스폰 할 수 있다.

 

 

 

1
2
Monster* ghostPrototype = new Ghost(153);
Spawner* ghostSpawner = new Spawner(ghostPrototype);
cs

유령을 만들어진 고스트 프로토타입을 만들고 스포너에 전달한다.

프로토 타입 패턴의 장점은 있지만

 

이러한 방법 보다는 요즘은 개체 종류별로 클래스를 만들기보다는

컴포넌트나 타입 객체로 모델링 하는것을 추천한다.

 

앞에까진 별도의 스포너 클래스가 필요했다.

하지만 다음과 같이 스폰 함수를 만들면 코드의 양이 줄어든다.

 

 

1
2
3
4
Monster* spawnGhost()
{
    return new Ghost();
}
cs

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
typedef Monster* (*SpawnCallBack)();
 
class Spawner 
{
public:
    Spawner(SpawnCallBack spawn) : spawn_(spawn) { }
    Monster* SpawnMonster() { return spawn_(); }
 
private:
    SpawnCallBack sapwn_;
};
 
 
Spawner* ghostSpawner = new Spawner(spawnGhost);
cs

이런 식으로 유령을 스폰하는 객체를 만들 수 있다.

 

특정 몬스터 클래스를 하드코딩하기 싫다면 템플릿 타입 매개변수를 전달하는 방법도 있다.

 

프로토 타입 언어 패러다임

객체지향 프로그래밍이 곧 클래스라고 생각한다.

oop는 데이터와 코드를 묶어주는 객체를 직접 정의 할 수 있도록 한다.

프로토타입 패턴의 장점은 클래스뿐만 아니라 상태도 같이 복제한다는 점이다. 원형 객체를 생성할 때 설정된 상태 그대로 복제한다.

 

그래도 결과적으로는 코드 양이 크게 줄어들지는 않는다.

또한 요즘은 몬스터 종류별로 클래스를 만들기보다는 컴포넌트나 타입객체로 모델링 하는것이 더 선호된다.

 

 

데이터 모델링을 위한 프로토타입

json 타입 데이터를 단순하게 만들 수 있는 방법중에 프로토타입 모델링을 사용하는 방법도 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
{
    "이름""고블린 보병",
    "기본체력"20,
    "최대체력"30,
    "내성": ["추위""독"],
    "약점": ["불""빛"]
}
 
{
    "이름""고블린 마법사",
    "기본체력"20,
    "최대체력"30,
    "내성": ["추위""독"],
    "약점": ["불""빛"]
    "마법": ["화염구""번개 화살"]
}
 
{
    "이름""고블린 궁수",
    "기본체력"20,
    "최대체력"30,
    "내성": ["추위""독"],
    "약점": ["불""빛"]
    "공격방법": ["단궁"]
 }
 
cs

위의 방법은 중복성이 많다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
 
{
    "이름""고블린 보병",
    "기본체력"20,
    "최대체력"30,
    "내성": ["추위""독"],
    "약점": ["불""빛"]
}
 
{
    "이름""고블린 마법사",
    "프로토타입""고블린 보병",
    "마법": ["화염구""번개 화살"]
}
 
{
    "이름""고블린 궁수",
    "프로토타입""고블린 보병",
    "공격방법": ["단궁"]
 }
 
cs

 

이런식으로 중복이 많은 데이터를 줄일 수 있다.

 

프로토타입은 기존 객체를 복제하거나, 추상 클래스를 만드는 대신 

위임을 통해 중복을 줄이는 방법이라고 할 수 있다.

'디자인패턴' 카테고리의 다른 글

상태 패턴 (State Pattern)  (0) 2024.03.26
싱글턴 패턴 (Singleton Pattern)  (1) 2024.03.22
관찰자(Observer) 패턴  (0) 2024.03.15
경량 패턴  (0) 2024.03.15
명령(command) 패턴  (0) 2024.03.11