policies
这个东西经常能在 boost 里面出现。前面我们提到了所谓的 strategy pattern,在那个鸭子设计里面我们将两个正交的操作 quack 和 fly 弄了出来,分成两个 interface,某种鸭子是这两个接口或者之一的实现者。这也是最常见的 OOP 的技巧,利用 virtual function。
这里我们介绍 Andrei 大牛提出的 policy 的实现,这可以看成是 compile-time strategy pattern。其想法是每个正交的成分使用 concept/policy 将其组织在一起,而最终的 client 继承/聚合各种 policy。我们仍然以鸭子为例:
struct none_type {} ;
template <class quack_policy = none_type, class fly_policy = none_type>
class duck : public quack_policy, public fly_policy {
} ;
class common_quack_policy {
public:
void quack() {
// common quack
}
} ;
class common_fly_policy {
public:
void fly() {
// common fly
}
} ;
duck<common_quack_policy, common_fly_policy> quackable_and_flyable_duck ;
duck<common_quack_policy> quackable_only_duck ;
在编译时我们的鸭子的行为就会被检查,quackable_only_duck 并没有 fly() 方法,因此试图让它 fly() 会产生编译错误。同时各种方法是 compile-time 绑定在鸭子身上,不同的鸭子是可以产生不同的行为的。这里的两个 policy 在 concept 上组织起来了各种鸭子的特性,而不同的鸭子并不是一类,也是一个鸭子的 concept。
这也是 boost 各种库使用的一种技巧。感觉上这种技巧可以解决一部分 vfun 运行时的问题,但是也丢失了继承这种组织的优点(可以用 vector 等容器直接管理)。
------------------
And Adam knew Eve his wife; and she conceived, and bore Cain, and said, I have gotten a man from the LORD.
[...] 这个前面讨论过是啥。好像优势主要是在 orthogonal 的 policy 能具有写 m + n 得到 mn 个东西的效果,暂时没想到一个特别有用的例子。 [...]
这个文章挺好的 « demonstrate 的 blog
2011/04/09 at 9:08 PM
[...] policy 的应用,我们后面也讨论过 g++ 中提供的额外的数据结构 [...]
policy-based class design « demonstrate 的 blog
2012/02/22 at 9:14 PM