Part 1. 1) Commander Pattern
Commander Pattern
•
Capsulate the command itself. Through this, make different users who have different inputs parameter, wait or logging the users’ requests and supporting the restore operation.
◦
= Command Patterns reify calling functions.
▪
“reifing” means changing the concept into object.
▪
“reifing calling functions” means that wrapping calling functions with objects
▪
it is equal to express callbacks (or function pointer) with OOP (Object-Oriented Programming)
Example
•
Changing the Input keys
X → JUMP()
Y → FURE_GUN()
Z → LURCH()
X → SWAP_WEAPON()
•
Before
void InputHandler::handleInput(){
if (isPressed(BUTTON_X) jump();
else if (isPressed(BUTTON_Y) fireGun();
}
Python
복사
•
After
class Command() {
public:
virtual ~Command() {}
virtual void execute {}
}
class JumpCommand() : public Command {
public:
virtual void execute() { jump(); }
}
class FireCommand() : public Command {
public:
virtual void execute() { fireGun(); }
}
class InputHandler {
public:
void handelInput();
private:
Command* buttonX_;
Command* buttonY_;
...
}
void InputHandler::handelInput() {
if(isPressed(BUTTON_X)) buttonX_->execute();
...
}
Python
복사
•
Constraints : the code has coupling; each function (jump & fire_gun()) finds character objects implicitly.
•
Solve: Pass the character object as a parameter
class JumpCommand: public Command {
public:
virtual void execute(GameActor& actor) {
actor.jump();
}
}
Python
복사
•
Key idea: one abstract class between actor and command
◦
From now on, we can handle all the actors cause we used Command Pattern by passing the actors as a parameter !
Other Use Case
•
Command Stream
◦
AI (Input Handler, Producer) → Command Stream → Actor (Dispatcher, Subscriber)
•
Undo Command
◦
define virtual method undo()
class Command() {
public:
virtual ~Command() {}
virtual void execute() = 0;
virtual void undo() = 0;
}
Python
복사
◦
store previous status into variables
class MoveUnitCommand : public Command() {
public:
MoveUnitCommand(Unit* unit, int x, int y) {
: unit_(unit), x_(x), y_(y), xBefore_(0), yBefore(0), x_(x), y_(y) { }
virtual void execute() {
//store previous satus into variables
xBefore = unit_->x();
yBefore = unit_->y();
unit_->moveTo(x_, y_);
virtual void undo() {
unit_-> moveTo(xBefore_, yBefore_);
}
private:
Unit* unit_;
int x_, y_;
int xBefore, yBefore;
};
Python
복사
•
Chain of Responsibility
◦
if objects can react to the command and can assign processing command to sub-objects, it could be the Chain of Responsiblity Pattern.
Summary
1.
I would say Commander Pattern is making abstract class for the command to do decoupling user’s input and actors
2.
Commander Pattern can be utilized to implement the undo function
Reference
•
There are some commands only have actions without status. If so, making many instances of the command classes are memory-wasting job. It can be solved by the Lightweight Patterns
This contents are originated from “Game Programming Patterns”, Robert, Hanbit Media Inc. (Korean Version)