Chatper 5 原型模式
核心思想是一个对象可以生成与自身相似的其他对象。
基类Monster,有一个抽象方法clone:
1 class Monster 2 { 3 public: 4 5 virtual ~Monster() {} 6 virtual Monster* clone() = 0; 7 8 // Other stuff... 9 };
子类的clone实现:
1 class Ghost : public Monster { 2 public: 3 4 Ghost(int health, int speed) 5 : health_(health), 6 speed_(speed) 7 {} 8 9 virtual Monster* clone() 10 { 11 return new Ghost(health_, speed_); 12 } 13 14 private: 15 int health_; 16 int speed_; 17 };
通用的Spawner类:
1 class Spawner 2 { 3 4 public: 5 Spawner(Monster* prototype) 6 : prototype_(prototype) 7 {} 8 9 Monster* spawnMonster() 10 { 11 return prototype_->clone(); 12 } 13 14 private: 15 Monster* prototype_; 16 };
这样用:
1 Monster* ghostPrototype = new Ghost(15, 3); 2 Spawner* ghostSpawner = new Spawner(ghostPrototype); 3 Monster* newGhost = Spawner->spawnMonster();
生成器函数和孵化函数指针:
1 Monster* spawnGhost() 2 { 3 return new Ghost(); 4 } 5 typedef Monster* (*SpawnCallback)(); 6 7 class Spawner 8 { 9 public: 10 Spawner(SpawnCallback spawn) 11 : spawn_(spawn) 12 {} 13 14 Monster* spawnMonster() 15 { 16 return spawn_(); 17 } 18 19 private: 20 SpawnCallback spawn_; 21 22 };
这样用:
1 Spawner* ghostSpawner = new Spawner(spawnGhost); 2 Monster* newGhost = ghostSpawner->spawnMonster();
Chatper 6 单例模式
确保一个类只有一个实例,并为其提供一个全局访问入口。
1 class FileSystem 2 { 3 public: 4 static FileSystem& instance() 5 { 6 static FileSystem *instance = new FileSystem(); 7 return *instance; 8 } 9 10 private: 11 FileSystem() {} 12 13 };
- 延迟初始化
- C++11保证局部静态变量的初始化只进行一次
- 多线程安全
- 私有构造函数
继承单例(多平台):
1 class FileSystem 2 { 3 public: 4 5 static FileSystem& instance(); 6 7 virtual ~FileSystem() {} 8 9 virtual char* readFile(char* path) = 0; 10 virtual void writeFile(char* path, char* contents) = 0; 11 12 protected: 13 FileSystem() {} 14 15 }; 16 17 class PS3FileSystem : public FileSystem 18 { 19 20 public: 21 virtual char* readFile(char* path) 22 { 23 // Use Sony file IO API... 24 } 25 26 virtual void writeFile(char* path, char* contents) 27 { 28 // Use sony file IO API... 29 } 30 }; 31 32 class WiiFileSystem : public FileSystem 33 { 34 35 public: 36 virtual char* readFile(char* path) 37 { 38 // Use Nintendo file IO API... 39 } 40 41 virtual void writeFile(char* path, char* contents) 42 { 43 // Use Nintendo file IO API... 44 } 45 46 };
Instance的编译跳转实现:
1 FileSystem& FileSystem::instance() 2 { 3 4 #if PLATFORM == PLAYSTATION3 5 static FileSystem *instance = new PS3FileSystem(); 6 #elif PLATFORM == WII 7 static FileSystem *instance = new WiiFileSystem(); 8 #endif 9 10 return *instance; 11 }
单例的缺陷:
- 全局变量,单例就是一个全局状态,只是被封装到了类中;
- 延迟初始化可能导致掉帧和卡顿,可能导致内存布局碎片化。
通过将全局对象类包装在现有类里来减少全局对象数量:
1 class Game 2 { 3 4 public: 5 static Game& instance() { return instance_; } 6 7 // Functions to set log_, et. al. ... 8 9 Log& getLog() { return *log_; } 10 11 FileSystem& getFileSystem() { return *fileSystem_; } 12 13 AudioPlayer& getAudioPlayer() { return *audioPlayer_; } 14 15 private: 16 static Game instance_; 17 Log *log_; 18 FileSystem *fileSystem_; 19 AudioPlayer *audioPlayer_; 20 21 }; 22 23 Game::instance().getAudioPlayer().play(VERY_LOUD_BANG);
Chatper 7 状态模式
允许一个对象在其内部状态改变时改变自身的行为,对象看起来好像是在修改自身类。
复杂的分支和可变的状态是两种最容易出错的代码。
状态、输入和转换:
1. 拥有一组数目较小的状态,可以在这组状态之间切换;
2. 同一时刻只能处于一种状态;
3. 响应用户输入和游戏事件
定义一个接口,enter函数定义一些进入状态时的处理,exit函数定义一些状态改变前的处理:
1 class HeroineState 2 { 3 4 public: 5 virtual ~HeroineState() {} 6 virtual void handleInput(Heroine& heroine, Input input) {} 7 virtual void update(Heroine& heroine) {} 8 9 virtual void enter(Heroine& heroine) {} 10 virtual void exit(Heroine& heroine) {} 11 12 };
每一个状态都继承这个状态接口:
1 class DuckingState : public HeroineState 2 { 3 4 public: 5 DuckingState() 6 : chargeTime_(0) 7 {} 8 9 virtual void handleInput(Heroine& heroine, Input input) { 10 if (input == RELEASE_DOWN) 11 { 12 // Change to standing state... 13 heroine.setGraphics(IMAGE_STAND); 14 } 15 } 16 17 virtual void update(Heroine& heroine) { 18 chargeTime_++; 19 if (chargeTime_ > MAX_CHARGE) 20 { 21 heroine.superBomb(); 22 } 23 } 24 25 private: 26 int chargeTime_; 27 28 };
主角类中有一个指针指向当前状态:
1 class Heroine 2 { 3 4 public: 5 virtual void handleInput(Input input) 6 { 7 state_->handleInput(*this, input); 8 } 9 10 virtual void update() 11 { 12 state_->update(*this); 13 } 14 15 // Other methods... 16 17 private: 18 HeroineState* state_; 19 20 };
静态状态(省CPU省内存):
1 class HeroineState 2 { 3 4 public: 5 static StandingState standing; 6 static DuckingState ducking; 7 static JumpingState jumping; 8 static DivingState diving; 9 10 // Other code... 11 }; 12 13 if (input == PRESS_B) 14 { 15 heroine.state_ = &HeroineState::jumping; 16 heroine.setGraphics(IMAGE_JUMP); 17 }
实例化状态(handleInput方法返回后删除原状态):
1 void Heroine::handleInput(Input input) 2 { 3 HeroineState* state = state_->handleInput(*this, input); 4 if (state != NULL) 5 { 6 delete state_; 7 state_ = state; 8 9 // Call the enter action on the new state. 10 state_->enter(*this); 11 } 12 } 13 14 HeroineState* StandingState::handleInput( 15 Heroine& heroine, Input input) 16 { 17 if (input == PRESS_DOWN) 18 { 19 // Other code... 20 return new DuckingState(); 21 } 22 23 // Stay in this state. 24 return NULL; 25 }
并发状态机(当两种状态没什么关系时):
1 class Heroine 2 { 3 4 // Other code... 5 6 private: 7 HeroineState* state_; 8 HeroineState* equipment_; 9 10 }; 11 12 void Heroine::handleInput(Input input) 13 { 14 state_->handleInput(*this, input); 15 equipment_->handleInput(*this, input); 16 }
如果两种状态有一些联系(不能太多),需要对某些状态处理进行干预,可以做一些简单的if判断并特殊处理下。
层次状态机:
一个状态有父状态,如果子状态不处理就交给他的父状态处理。用来处理可能包含的大量相似状态。
1 class OnGroundState : public HeroineState 2 { 3 4 public: 5 virtual void handleInput(Heroine& heroine, Input input) 6 { 7 if (input == PRESS_B) 8 { 9 // Jump... 10 } 11 else if (input == PRESS_DOWN) 12 { 13 // Duck... 14 } 15 } 16 }; 17 18 class DuckingState : public OnGroundState 19 { 20 21 public: 22 virtual void handleInput(Heroine& heroine, Input input) 23 { 24 if (input == RELEASE_DOWN) 25 { 26 // Stand up... 27 } 28 else 29 { 30 // Didn't handle input, so walk up hierarchy. 31 OnGroundState::handleInput(heroine, input); 32 } 33 } 34 };
下推自动机:
开火时push Firing,结束后pop掉开火状态,状态机自动返回开火前的状态。
来源:https://www.cnblogs.com/pandawuwyj/p/6256800.html