访问者模式:重新定义对某个对象中各个元素的操作,在不改变数据结构的前提下,定义作用于这些元素的新操作。
玩游戏的时候,经常会遇到各种各样的怪物,有的是级别比较低的怪物,有的是级别比较高的怪物,像终极的大BOSS。小级别的怪物比较好打,但是大级别的怪物就比较难打了,需要多次技进攻才可以。小级别的怪物之所以难打是因为他的生命值比较少,在打怪物的过程中可以时刻查看怪物的生命值,根据他们的生命值可以实时的调整攻击策略。
定义一个怪物的基类:
class IMonsterVisitor;
//怪物基类
class IMonster {
public:
IMonster(std::string name);
~IMonster();
std::string getName();
void setLife(int l);
int getLife();
void setATK(int a);
int getATK();
void setDEF(int d);
int getDEF();
virtual void prinfInfo(IMonsterVisitor* v);
protected:
std::string _name;//怪物名称
int _life;//生命值 0 - 100
int _atk;//攻击力 0 - 100
int _def;//防御力 0 - 100
};
IMonster::IMonster(std::string name) {
_name = name;
_life = 100;
_atk = 100;
_def = 100;
}
IMonster::~IMonster() {
}
std::string IMonster::getName() {
return _name;
}
void IMonster::setLife(int l) {
_life = l;
}
int IMonster::getLife() {
return _life;
}
void IMonster::setATK(int a) {
_atk = a;
}
int IMonster::getATK() {
return _atk;
}
void IMonster::setDEF(int d) {
_def = d;
}
int IMonster::getDEF() {
return _def;
}
void IMonster::prinfInfo(IMonsterVisitor* v) {
}
大家看到了,定义一个访问对象各种属性的函数:
virtual void prinfInfo(IMonsterVisitor* v);
这个函数有一个参数,IMonsterVisitor*这个参数主要是用来访问对象内部的各种状态数据的。
然后在定义不同级别的怪物:
//小怪
class SmallMonster :public IMonster {
public:
SmallMonster(std::string n);
void prinfInfo(IMonsterVisitor* v)override;
};
//终极大怪
class BossMonster :public IMonster {
public:
BossMonster(std::string n);
void prinfInfo(IMonsterVisitor* v)override;
};
SmallMonster::SmallMonster(std::string n) :IMonster(n){
}
void SmallMonster::prinfInfo(IMonsterVisitor* v) {
v->visit(this);
}
BossMonster::BossMonster(std::string n) : IMonster(n) {
_life = 1000;
_atk = 1000;
_def = 1000;
}
void BossMonster::prinfInfo(IMonsterVisitor* v) {
v->visit(this);
}
小怪和终极打怪都定义完成了,下面就要定义访问者了。
定义访问者的基类:
class IMonster;
class SmallMonster;
class BossMonster;
class IMonsterVisitor {
public:
IMonsterVisitor();
~IMonsterVisitor();
virtual void visit(IMonster* m);
virtual void visit(SmallMonster* m);
virtual void visit(BossMonster* m);
};
IMonsterVisitor::IMonsterVisitor() {
}
IMonsterVisitor::~IMonsterVisitor() {
}
void IMonsterVisitor::visit(IMonster* m) {
}
void IMonsterVisitor::visit(SmallMonster* m) {
}
void IMonsterVisitor::visit(BossMonster* m) {
}
具体的访问者:
class MonsterVisitor :public IMonsterVisitor {
public:
virtual void visit(IMonster* m);
virtual void visit(SmallMonster* m);
virtual void visit(BossMonster* m);
};
void MonsterVisitor::visit(IMonster* m) {
printf("普通怪物:%s 生命值:%d 攻击力:%d 防御力:%d\n"
, m->getName().c_str(), m->getLife(), m->getATK(), m->getDEF());
}
void MonsterVisitor::visit(SmallMonster* m) {
printf("小怪:%s 生命值:%d 攻击力:%d 防御力:%d\n"
, m->getName().c_str(), m->getLife(), m->getATK(), m->getDEF());
}
void MonsterVisitor::visit(BossMonster* m) {
printf("终极大怪:%s 生命值:%d 攻击力:%d 防御力:%d\n"
, m->getName().c_str(), m->getLife(), m->getATK(), m->getDEF());
}
下面看看场景:
int main() {
IMonster* s1 = new SmallMonster("虾兵");
IMonster* s2 = new SmallMonster("蟹将");
IMonster* b = new BossMonster("龙王怪");
IMonsterVisitor* visitor = new MonsterVisitor;
//游戏玩家遭遇龙王带领的虾兵蟹将的进攻,查看一下它们初始状态
s1->prinfInfo(visitor);
s2->prinfInfo(visitor);
b->prinfInfo(visitor);
//经过一番搏斗后,打退了龙王的进攻
s1->setLife(50);
s2->setLife(40);
b->setLife(500);
s1->prinfInfo(visitor);
s2->prinfInfo(visitor);
b->prinfInfo(visitor);
return 0;
通过访问者模式就实现了数据加载和数据展示的分离。怪物的创建和怪物的展示分别有不同的对象来实现,极大的方便的扩展,比如说我只想显示怪物的攻击了和防御力等。
访问者模式优点:
1.实现了对象的职责分离;
2.扩展性较好,比如扩展其他的一些数据操作功能。