/*条款35:考虑virtual函数以外的其他选择*/
#include<iostream>
using namespace std;
/*
class GameCharacter {//
public:
virtual int healthValue()const;//返回人物的健康指数,子类会根据具体的人物角色来计算,而且这里并未声明为纯虚,暗示我们将会有个计算健康指针的缺省算法
//但是不一定只有这一种实现方法
};
*/
//NVI手法实现template method模式
//一种思想流派主张虚函数应该几乎总是私有的,并且建议保留halthValue公有,但把它变成NV,并调用一个 private virtual
class GameCharacter {
public:
int healthValue()const {//子类不重新定义它
//。。。 //事前工作 如加锁,验证,运转日志
int retVal = doHealthValue();//做真正的工作
//... //做一些事后工作如 释放互斥锁,再次验证
return retVal;
}
//private:
protected:
virtual int doHealthValue()const {//外覆器wrapper
//缺省算法,计算健康指数
}
};/*优点 :1可以增加一些附带的必要工作
2 基类保留诉说“函数何时被调用”的权利,而子类也被赋予了“如何实现机能”的控制能力(私有的虚函数,可以在子类中重新定义)
缺点: 如果子类中需要调用这个虚函数就变的困难了,为了调用合法只能声明为保护,有时甚至必须是公开(具备多态性质的析构)这样就不能用NVI手法 了
*/
class ACharacter:public GameCharacter {
public:
void doHealthValue() {
}
void funcallVfun(){
GameCharacter::doHealthValue();
}
};
//----------------------------function pointer 实现strategy模式
//这类设计主张“人物健康指数的计算与人物类型无关”可以把每个人物的构造函数接受一个函数指针,指向的函数做健康计算
class GameCharacter; //前置声明
int defaultHealthCalc(const GameCharacter&gc){}
class GameCharacter {
public:
typedef int(*HealthCalcFunc)(const GameCharacter&);
explicit GameCharacter(HealthCalcFunc hcf = defaultHealthCalc):healthFunc(hcf){}
int healthValue()const {
return healthFunc(*this);
}
HealthCalcFunc healthFunc;
};
/*这个模式提供了某些有趣的弹性
1 同一人物不同实体可以有不同的健康计算函数 如下
2 某已知人物健康指数计算函数可在运行期变更 可以在基类中再添加 一个成员函数 用来替换当前健康计算函数
换句话说健康指数计算不再是基类继承体系内的成员函数 这些计算函数并未特别访问要被计算的对象,如defaultHealthCalc 并未访问EvilBadGuy的non-public成分
*/
class EvilBadGuy:public GameCharacter {
};
int loseHealthQuickly(const GameCharacter&);//健康计算函数1,2
int loseHealthSlowly(const GameCharacter&);
EvilBadGuy ebg1(loseHealthQuickly);
EvilBadGuy ebg2(loseHealthSlowly);
//---------------tr1::funtion完成strategy模式
class GameCharacter;
int defaultHealthCalc(const GameCharacter& gc);
class GameCharacter {
public:
typedef std::tr1::is_function<int(const GameCharacter&)>HealthCalcFunc;
explicit GameCharacter(HealthCalcFunc hcf=defaultHealthCalc):healthFunc(hcf){}
int healthValue()const {
return healthFunc(*this);
}
private:
HealthCalcFunc healthFunc;
};
/*与函数指针不同的是 GameCharacter 持有一个函数对象 相当于一个指向函数的泛化的指针
但它有更惊人的弹性
*/
short calcHealth(const GameCharacter&);//返回值 非int
struct HealCalculator {
int operator()(const GameCharacter&)const {
}
};
class GameLevel {
public:
float health(const GameCharacter&)const;//计算健康 返回值非int
};
class EvilBadGuy:public GameCharacter{
}
class EyeCandyCharacter :public GameCharacter {
//另一个人物类型 假设其构造函数与EvilBadGuy同
};
EvilBadGuy dbg1(calcHealth);//使用某个函数计算健康指数
EyeCandCharacter ecc1(HealthCalculator());//使用某个函数对象计算健康指数
GameLevel currentLevel;
EvilBadGuy ebg2(std::tr1::bind(&GameLevel::health, currentLevel, _1);
//上面没看懂。。。。
//古典strategy模式
//是将健康计算函数做成一个分离的继承体系中的虚成员函数
class GameCharacter;
class HealthCalcFunc {
public:
virtual int calc(const GameCharacter&gc)const {
}
};
HealthCalcFunc defaultHealthCalc;
class GameCharacter {
public:
explicit GameCharacter(HealthCalFunc*phcf=&defaultHealthCalc):pHealthCalc(phcf){}//提供了默认构造
int healthValue()const {
return pHealthCalc->calc(*this);
}
private:
HealthCalcFunc*pHealthCalc;
};
条款35:考虑virtual函数以外的其他选择
最新推荐文章于 2021-12-18 12:33:19 发布