C++设计模式-访问者模式详解

访问者模式:重新定义对某个对象中各个元素的操作,在不改变数据结构的前提下,定义作用于这些元素的新操作

玩游戏的时候,经常会遇到各种各样的怪物,有的是级别比较低的怪物,有的是级别比较高的怪物,像终极的大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;

运行结果:
C++设计模式-访问者模式详解_第1张图片

通过访问者模式就实现了数据加载和数据展示的分离。怪物的创建和怪物的展示分别有不同的对象来实现,极大的方便的扩展,比如说我只想显示怪物的攻击了和防御力等。

访问者模式优点:
1.实现了对象的职责分离;
2.扩展性较好,比如扩展其他的一些数据操作功能。

你可能感兴趣的:(c++,设计模式)