2010年5月26日水曜日

C++でTemplateMethodパターン

TemplateMethodパターンはスーパークラス(ベースクラス)でロジックの概要設計あるいは共通部分を実装し、詳細ロジックあるいは非共通部分をサブクラスで提供するパターンです。
大げさに言うとスーパークラスでプチフレームワークを実装するようなイメージです。
TemplateMethodパターンのメリットは
  • サブクラスで共通なロジックをスーパークラスで共通化できる。
  • ロジックの骨組みが明確になっている為、コードが把握し安い且つメンテナンスコストが軽減されやすい。
などです。
それではクラス図をご覧ください。
ちょっとメソッドとか多いですけど簡単な継承関係です。
このクラス図で重要なのは
  • move()
  • canMove()
  • canMoveEach()
  • moveEach()
で、Characterクラスのmove()がテンプレートメソッドに相当します。
次にソースを見てみましょう、用意するのは次のファイルです今回からクラスのcppファイルを用意しない方が見やすいかなと思って.hだけ用意しました。
  • main.cpp
  • Character.h
  • Monster.h
Character.h
  1. #ifndef _CHARACTER_H_  
  2. #define _CHARACTER_H_  
  3.   
  4. #include <stdio.h>  
  5.   
  6. class Character  
  7. {  
  8.     //----------------------------------  
  9.     //  field  
  10.     //----------------------------------  
  11. private:  
  12.     int HP;  
  13.     int MP;  
  14.   
  15.     //----------------------------------  
  16.     //  property  
  17.     //----------------------------------  
  18. public:  
  19.     const int getHP() {  
  20.         return this->HP;  
  21.     }  
  22.     Character& setHP(const int _hp) {  
  23.         this->HP = _hp;  
  24.         return *this;  
  25.     }  
  26.     const int getMP() {  
  27.         return this->MP;  
  28.     }  
  29.     Character& setMP(const int _mp) {  
  30.         this->MP = _mp;  
  31.         return *this;  
  32.     }  
  33.   
  34.     //----------------------------------  
  35.     //  method  
  36.     //----------------------------------  
  37. public:  
  38.     Character() :  
  39.         HP(100),  
  40.         MP(100)  
  41.     {  
  42.         //  do nothing...  
  43.     }  
  44.   
  45.     virtual ~Character() {  
  46.         //  do nothing...  
  47.     }  
  48.   
  49.     void move() {   //  テンプレートメソッド  
  50.         //  move可能判定  
  51.         if (this->canMove()) {  
  52.             //  move  
  53.             this->moveEach();  
  54.         }  
  55.     }  
  56. private:  
  57.     virtual const bool canMove() {  
  58.         //  HPが0ならmove不可  
  59.         if (this->getHP() <= 0) {  
  60.             return false;  
  61.         }  
  62.         return this->canMoveEach();  
  63.     }  
  64.   
  65. protected:  
  66.     virtual const bool canMoveEach() = 0;  
  67.     virtual void moveEach() = 0;  
  68. };  
  69. #endif  
  70. </stdio.h>  
move()のなかでmove可能ならばmoveするという大まかなロジックを実装しています。

Monster.h
  1. #ifndef _MONSTER_H_  
  2. #define _MONSTER_H_  
  3.   
  4. #include "Character.h"  
  5.   
  6. class Monster : public Character  
  7. {  
  8.  //----------------------------------  
  9.  // method  
  10.  //----------------------------------  
  11. protected:  
  12.  virtual ~Monster() {  
  13.   // do nothing...  
  14.  }  
  15.  virtual const bool canMoveEach() {  
  16.   printf("canMoveEach\n");  
  17.   return true;  
  18.  }  
  19.   
  20.  virtual void moveEach() {  
  21.   printf("moveEach\n");  
  22.  }  
  23. };  
  24. #endif  
Monster独自のcanMove()、move()をcanMoveEach()、moveEach()で実装しています。Eachっていう名前の付け方は一般的ではない気がします。

main.cpp
  1. #include <stdio.h>  
  2. #include "Monster.h"  
  3.   
  4. void main(void)  
  5. {  
  6.     //  Monster生成  
  7.     Character* character = new Monster();  
  8.   
  9.     //  move  
  10.     character->move();  
  11.   
  12.     //  HPに0を設定  
  13.     character->setHP(0);  
  14.   
  15.     //  move  
  16.     character->move();  
  17.   
  18.     delete character;  
  19.     printf("hit any key...\n");  
  20.     while(getchar() == EOF) {}  
  21. }  
  22. </stdio.h>  

0 件のコメント:

コメントを投稿