zoukankan      html  css  js  c++  java
  • 状态模式(state)C++实现

    状态模式

           当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。

           状态模式主要解决的是当控制一个对象状态转换的条件表达式过于复杂时的情况。把状态的判断逻辑转移到表示不同状态的一系列类当中,可以把复杂的判断逻辑简化。

           将与特点状态相关的行为局部化,并且将不同状态的行为分割开来!

    UML:

      

    代码实现:

      以前很喜欢玩war3里面的国家对抗,是一个建造类游戏。里面的建筑在不同的时候有不同的状态,例如兵营在产兵的时候会发白光,

    受伤的时候会着火,建造的时候有建筑特效。兵营在建造没完成的时候不能升级和产兵,升级的时候不能产兵,受伤着火了也能继续产兵或升级。

    假设这些建筑的状态和表现为:建造-建造特效、受伤-受伤着火、升级-升级蓝光、生成-生产白光、修复-修复绿光。

    实现各种状态代码state.h:

     1 #ifndef STATE_H
     2 #define STATE_H
     3 #include <iostream>
     4 using namespace std;
     5 
     6 class absState{
     7 public:
     8     virtual void show() = 0;
     9 };
    10 
    11 class buildingState:public absState{
    12 public:
    13     virtual void show()
    14     {
    15         cout<<"建造特效  ";
    16     }
    17 };
    18 
    19 class fireState:public absState{
    20 public:
    21     virtual void show()
    22     {
    23         cout<<"受伤着火  ";
    24     }
    25 };
    26 
    27 class productionState:public absState{
    28 public:
    29     virtual void show()
    30     {
    31         cout<<"生产白光  ";
    32     }
    33 };
    34 
    35 class upGradeState:public absState
    36 {
    37 public:
    38     virtual void show()
    39     {
    40         cout<<"升级蓝光  ";
    41     }
    42 };
    43 
    44 class repairState:public absState
    45 {
    46 public:
    47     virtual void show()
    48     {
    49         cout<<"修复绿光  ";
    50     }
    51 };
    52 #endif

    建筑实现代码building.h:

     1 #ifndef BUILDING_H
     2 #define BUILDING_H
     3 #include "state.h"
     4 
     5 #include <map>
     6 #include <iostream>
     7 using namespace std;
     8 
     9 enum StateType
    10 {
    11     BUILDING, INJURED, REPAIR, UPGRADE, PRODUCTION
    12 };
    13 
    14 class absBuilding
    15 {
    16 public:
    17     absBuilding(char* name):mName(name){}
    18     virtual void show() 
    19     {
    20         cout<<mName<<"表现:"<<endl;
    21         map<StateType, absState*>::iterator beg = mStates.begin();
    22         for ( ; beg != mStates.end(); beg++)
    23         {
    24             beg->second->show();
    25         }
    26         cout<<endl;
    27     };
    28     void eraseState(StateType type)  //实现删除一个特效
    29     {
    30         auto result = mStates.find(type);
    31         if(result != mStates.end())
    32             mStates.erase(result);
    33     }
    34 protected:
    35     char* mName;
    36     map<StateType, absState*> mStates;
    37 };
    38 
    39 class concreteBuilding:public absBuilding
    40 {
    41 public:
    42     concreteBuilding(char* name):absBuilding(name)
    43     {
    44         mStates[BUILDING] = new buildingState();
    45     }
    46     void upGrade()
    47     {
    48         auto result = mStates.find(UPGRADE);
    49         if(result == mStates.end())
    50         {
    51             mStates[UPGRADE] = new upGradeState();
    52         }
    53         eraseState(BUILDING);    //升级的时候必须是建造过程已经结束,所以需要删掉“建筑”状态
    54         eraseState(PRODUCTION);   //升级的时候不能进行生产
    55     }
    56     void production()
    57     {
    58         auto result = mStates.find(PRODUCTION);
    59         if(result == mStates.end())
    60         {
    61             mStates[PRODUCTION] = new upGradeState();
    62         }
    63         eraseState(BUILDING);  //生产的时候必须已经建造完成
    64         eraseState(UPGRADE);   //生产的时候不能升级
    65     }
    66     void injured()
    67     {
    68         auto result = mStates.find(INJURED);
    69         if(result == mStates.end())
    70         {
    71             mStates[INJURED] = new fireState();
    72         }74     }
    75     void repair()
    76     {
    77         auto injuredVal = mStates.find(INJURED);
    78         if(injuredVal == mStates.end())
    79             return;
    80         auto result = mStates.find(REPAIR);
    81         if(result == mStates.end())
    82         {
    83             mStates[REPAIR] = new repairState();
    84         }86     }
    87 };
    88 
    89 #endif

    客户端代码main.cpp:

     1 #include <iostream>
     2 #include "tank.h"
     3 #include "building.h"
     4 
     5 using namespace std;
     6 class SiegeTank;
     7 
     8 void main()
     9 {
    10     concreteBuilding cb("兵营");
    11     cb.production();
    12     cb.injured();
    13     cb.repair();
    14     cb.show();
    15     return;
    16 }

    结果:

  • 相关阅读:
    Prometheus入门教程(二):Prometheus + Grafana实现可视化、告警
    Prometheus 入门教程(一):Prometheus 快速入门
    Prometheus 系列开篇:为什么要学 Prometheus ?
    你总是遗憾,是因为你还没想好,你的一生想怎么过!
    搞 Java 的年薪 40W 是什么水平?
    闪送,为何能从顺丰中杀出一条血路?
    安全攻击溯源思路及案例
    Windows下登录凭证窃取技巧
    Linux下登录凭证窃取技巧
    如何探测内网存活主机
  • 原文地址:https://www.cnblogs.com/wrbxdj/p/5361004.html
Copyright © 2011-2022 走看看