Command 패턴
실행할 명령을 클래스 묶음으로 만들어 실행할 객체에 명령들을 전송한다
함수로 명령을 실행하지 않고 클래스로 만들어 명령을 전송한다는게 핵심인데
한가지 더 핵심은 액터가 그냥 자기 자신 내에서 자신의 상태만 업데이트 할 수 있게 한다는
부가적인 개념을 더한다면 딱이다
이를 잘만 활용하면 실행 취소 재실행 을 만들 수도 있다
또한 키보드 바인딩에 사용 할 수도 있다
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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
|
#include<iostream>
#include<string>
#include<vector>
class Actor
{
public:
virtual void jump() {
std::cout << _who << "\t";
}
virtual void Attack() {
std::cout << _who << "\t";
}
virtual void Walk(float speed) {
std::cout << _who << speed << "만큼 \t";
}
std::string _who;
};
class Player : public Actor
{
public:
Player() {
_who = "Player";
}
void jump() {
Actor::jump();
std::cout << "점프" << std::endl;
}
void Attack() {
Actor::Attack();
std::cout << "공격" << std::endl;
}
void Walk(float speed) {
Actor::Walk(speed);
std::cout << "걷기" << std::endl;
}
};
class AI : public Actor
{
public :
AI() {
_who = "AI";
}
void jump() {
Actor::jump();
std::cout << "점프" << std::endl;
}
void Attack() {
Actor::Attack();
std::cout << "공격" << std::endl;
}
void Walk(float speed) {
Actor::Walk(speed);
std::cout << "걷기" << std::endl;
}
};
|
cs |
여기 부터는 명령들을 클래스화 시켜서 추상화
부모 클래스에만 virtual 붙였다고 구조가 복잡해지면 자식함수가 불리지 않는다는
몰상식한 발언은 삼가합시다
이런 사람의 케이스는 구조가 복잡해져서 호출이 안되는게 아니라 어딘가 잘못 만들어 놓고
왜 호출이 안되는지 이해를 못하는 경우입니다 ( more practice with C++ )
(예전에 이런 무식한 발언을 한 사람이 있었기에 생각나서 적어봄... 그냥 흘려 들으시길..)
virtual 을 자식에 붙이는건 그냥 관용적인 표현임..
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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
|
class Command
{
public :
virtual void execute(Actor* actor) = 0;
};
class JumpCommand : public Command
{
public:
void execute(Actor* actor)
{
actor->jump();
}
};
class AttackCommand : public Command
{
public:
void execute(Actor* actor)
{
actor->Attack();
}
};
class WalkCommand : public Command
{
public:
WalkCommand(float speed) : _speed(speed)
{
}
void execute(Actor* actor)
{
actor->walk(_speed);
}
float _speed;
};
//여기부트는 메인 구문
int main()
{
//명령들을 한데 모읍니다
std::vector<Command*> commandNodes;
JumpCommand ji;
AttackCommand ai;
commandNodes.push_back(&ji);
commandNodes.push_back(&ai);
//이련 명령들을 쌓아놓으면 실행 취소와 재 실행 또한 구현 할 수 있다
Player pIns;
AI aIns;
for each (auto node in commandNodes)
{
node->execute(&pIns); //액터에 명령 전송
}
std::cout << std::endl;
for each (auto node in commandNodes)
{
node->execute(&aIns);
}
return 0;
}
|
cs |
실행 결과
Player 점프
Player 공격
AI 점프
AI 공격
Actor 에 어떤 동작이 있다는 것이 정해져 있고 실행할 명령들을 모아 한번에 처리 ㄱ ㄱ
실행 취소는
여기서 알 수 있는 것은 Command 를 상속 받는 자식 Command 클래스들은 내부를 좀 더 자유롭게 작성 할 수 있다는 것을 알 수 있게 된다,
그래서
의 Command 들이 있다고 했을때 DoCommand 를 통과하명 명령이 실행 되고
UnDoCommand 를 명령어들이 통과되면 반대로 실행 되도록 하위 클래스에서 인자 값들을 조정 구현 해 주면 된다
또한 이렇게 두가지 Command 를 두는것도 있지만 명령들을 한대 놔두고 새로운 인스턴스 Actor 를 만들어 그동안 쌓아왔던 명령들을 원하는 부분까지 실행 시키게 하면 그것또한 실행 취소가 가능한 방법이다
함수 인자를 (람다 ~ Closure 클로저) 로 처리하여 좀 더 유연하게 처리 할 수도 있다
관련 글 http://3dmpengines.tistory.com/1593
'디자인패턴과방법론 > 디자인패턴' 카테고리의 다른 글
컴포넌트 패턴 component System(component pattern) (2) | 2016.03.07 |
---|---|
디자인패턴 한줄 정리 (0) | 2015.11.18 |
adaptor 패턴 (0) | 2015.11.17 |
Command pattern (0) | 2015.07.17 |
게임 오브젝트 설계 #4 - 메시지 통신(messaging) (0) | 2015.07.05 |