《Effective C++》条款35 Strategy 模式写法记录

Non-Virtual Interface (NVI) 手法实现

这个方法主张 virtual 函数应该几乎总是 private。这个流派认为,较好的设计是保留 healthValuepublic 成员函数,但让它成为 non-virtual ,并调用一个 private virtual 函数进行实际工作

class GameCharacter{
public:
	int healthValue() const{				// derived classes 不重新定义它
		...									// 一些事前工作
		int retVal = doHealthValue();		// 真正的工作
		...									// 时候工作
		return retVal;
	}
	...
private:
	virtual int doHealthValue() const{		// derived classes 可重新定义它
		...									// 缺省算法,计算相关值
	}
};

Function Pointer 实现 Strtegy 模式

class GameCharacter;			// 前置声明
// 以下函数时计算健康指数的缺省算法
int defaultHealthCalc(const GameCharacter& gc);
class GameCharacter{
public:
	typedef int (*HealthCalcFunc)(const GameCharacter&); // typedef了一个函数指针类型
	explicit GameCharacter(HealthCalcFunc hcf = defaultHealthCalc) : healthFunc(hcf){}
	int healthValue() const
	{ return healthFunc(*this); }
	...
private:
	HealthCalcFunc healthFunc;
};

这种方式相对更常见

  • 同一任务类型之不同实体可以有不同的健康计算函数
class EvilBadGuy:public GameCharacter{
public:
	explicit EvilBadGuy(HealthCalcFunc hcf = defaultHealthCalc)
	: GameCharacter(hcf)
	{...}
};
int loseHealthQuickly(const GameCharacter&);	// 健康指数计算函数1
int loseHealthSlowly(const GameCharacter&);		// 健康指数计算函数2

EvilBadGuy ebg1(loseHealthQuickly);				// 相同类型的人物搭配
EvilBadGuy ebg2(loseHealthSlowly);				// 不同的健康计算方式

藉由 tr1::function 完成 Strategy 模式

通过 tr1:function 接触了之前要求必须是个函数,而不能是某种 “象函数的东西” (例如函数对象) 的限制

tr1::function:
	
	class GameCharacter;
	int defaultHealthCalc(const GameCharacter& gc);
	class GameCharacter{
	public:
		// HealthCalcFunc 可以是任何 "可调用物" (callable entity), 可被调用并接受
		// 任何兼容于 GameCharacter 之物,返回任何兼容于 int 的东西
		typedef std::tr1::function<int (const GameCharacter&)> HealthCalcFunc;
		explicit GameCharacter(HealthCalcFunc hcf = defaultHealthCalc)
		: healthFunc(hcf)
		{}
		int healthValue() const
		{ return healthFunc(*this); }
	private:
		HealthCalcFunc healthFunc;
	};

实例:
short calcHealth(const GameCharacter&);	// 健康计算函数
										// 其返回类型是 non-int
struct HealthCalculator{				// 为计算健康而设计的函数对象
	int operator()(const GameCharacter&) const
	{ ... }
};

class GameLevel{
public:
	float health(const GameCharacter&) const;	// 成员函数,用以计算健康
	...											// 注意其 not-int 返回类型
};

class EvilBadGuy:pulic GameCharacter{	// 同前
	...
};

class EyeCandyCharacter:public GameCharacter{	// 另一个任务类型
	...											// 假设其构造函数与
};												// EvilBadGuy 同

EvilBadGuy ebg1(calcHealth);					// 人物1,使用某个
												// 函数计算

EyeCandyCharacter ecc1(HealthCalculator());		// 人物2,使用某个
												// 函数对象计算

// Effective C++ P175
GameLevel currentLevel;
...
EvilBadGuy ebg2(								// 人物3,使用某个
	std::str1::bind(&GameLevel::health,			// 成员函数计算
					currentLevel,
					_1)
);

古典 Strategy 模式

《Effective C++》条款35 Strategy 模式写法记录

class GameCharacter;		// 前置声明
class HealthCalcFunc{
public:
	... 
	virtual int calc(const GameCharacter& gc) const
	{ ... }
	...
};

Health	CalcFunc defaultHealthCalc;
class GameCharacter{
public:
	explicit GameCharacter(HealthCalcFunc* phcf = &defaultHealthCalc)
	: pHealthCalc(phcf)
	{}
	int healthValue() const
	{ return pHealthCalc->calc(*this); }
	...
private:
	HealthCalcFunc* pHealthClac;
};
上一篇:mybatis-plus自动生成代码以及page的使用


下一篇:Mybatis Plus代码生成器