Policy 和 Policy Classes有助于我们设计出更加安全,有效率且具有高度弹性的“设计元素”。所谓Policy,是用来定义一个class或者class template的接口,该接口以下项目之一或者全部组成:内隐类型定义,成员函数,成员变量。
template
Policies接口和一般传统的classes接口(纯虚函数集)不同,它比较松散,因为Policies是语法导向而非标记导向,比如:Creator明确定义的是“怎样的语法构造符合其所规范的class”,而非“必须重写哪些函数”,例如Creator Policy并没有规范Create()必须是静态的或者是虚函数,它只要求class必须定义出Create(),此外规定Create()应该(但非必须)传回一个指向新对象的指针。
如果又下面一个类设计需要适用Policy作为其基础类:
template
当具体实例化的时候我们必须传进去一个他所期望的Policy:
typedef WidgetManager<OpNewCreator<Widget> > MyWidgetMgr;
但是Policy的Template引数往往是多余的&#xff0c;因为实例化的对象往往已经在定义之前就已经确定了他的操作对象&#xff0c;比如上面的WidegManager总是操作Widget对象&#xff0c;所以完全没有必要每次实例化的时候再进行传入操作&#xff0c;这样既多余而且危险。
这个时候程序库可以使用“Template Template参数“来描述Policies&#xff0c;如下&#xff1a;
template class CreationPolicy > class WidgetManager : public CreationPolicy
要注意的是上面的Created引数其实只是一个形式引数&#xff0c;因此没有什么作用&#xff0c;可以省略。
typedef WidgetManager<OpNewCreator > MyWidgetMgr;
一个重要的细节就是Policy Class的析构函数&#xff0c;大多数的继承类会以公共继承的方式从某些Policies派生而来&#xff0c;因此使用者可以将一个这样的继承类自动转为一个Policy Class&#xff0c;并于稍后Delete该指针&#xff0c;除非Policy Class定义了 一个虚析构函数&#xff0c;否则Delete一个指向Policy Class的指针会产生不可预期的结果。
typedef MyWidgetManager<PrototypeCreator > MyWidgetManager;
....
MyWidgetManager wm;
PrototypeCreator<Widget>* pCreator &#61; &wm;
delete pCreator;
如果给Policy定义一个虚拟的析构函数&#xff0c;会妨碍Policy的静态结连特性&#xff0c;也会影响执行效率。许多的Policies并无任何的成员数据&#xff0c;纯粹只规范行为。第一个虚拟函数被加入会为对象大小带来额外的开销&#xff08;以为加入一份Vptr表&#xff09;&#xff0c;所以虚析构函数应该尽可能的避免。所以我们可以采用一个轻便而有效率的解法——定义一个非虚析构&#xff0c;如下&#xff1a;
template<class T >
struct OpNewCreator
{
static T* Create()
{
return new T;
}
protected:
~OpNewCreator() {}
};
我们可以将Policies组合起来&#xff0c;一般而言&#xff0c;一个高度可组装化的class会运用数个Policies来达成其运作上的各个方面。一个程序库使用者可以藉由组合不同的Policy Classes来选择他所需的高阶行为。
而建立一个基于Policy的类设计的最困难的部分&#xff0c;便是如何将Class正确的分解为Policies。一个准则就是&#xff0c;将参与Class行为的设计鉴别出来并命名。任何事情只要能以一种以上的方法解决&#xff0c;都应该被分析出来&#xff0c;并从Class中移出来成为一个Policy。
“设计“就是一种”选择“。大多数时候我们的困难并不在于找不到解决方案&#xff0c;而是又太多的解决方案。你必须知道哪一组方案可以圆满解决问题。大至构架层面&#xff0c;小至代码片段&#xff0c;都需要选择。此外&#xff0c;抉择是可以组合的&#xff0c;这给设计带来了可怕的多样性。Policies机制由templates和多重继承组成。一个Class如果适用了Polices&#xff0c;我们称其为host class&#xff0c;那是一个拥有多个template参数的class template&#xff0c;每一个参数代表一个policy。围绕着Policies而设计出来的class&#xff0c;支持可扩充的行为和优雅的机能消减。由于采用公共继承的原因&#xff0c;Policy得以通过host class提供追加功能。而host class也能运用”Policy提供的选择性机能“实例出更丰富的功能。