策略模式(设计模式——策略模式)大家耳熟能详,简言之,策略模式基于运虚表指针实现多态,但运行时的多态是有时间成本的。对于性能要求高的场景,策略模式反而不是最优选择。
Policy-based design(基于策略的设计)是一种现代C 编程中的高级泛型编程技术,基于模板或继承来定义一组可插拔的策略,每个策略代表一种特定的行为或特性。通过组合不同的策略,可以创建出具有不同功能特性的类实例,从而在不牺牲灵活性的前提下增加代码重用性和可扩展性。
与策略模式相比,策略模式侧重于在运行时动态切换行为,适用于OOP环境,主要通过对象组合和多态性实现。Policy-based Design则是在编译时期静态确定行为,适用于泛型编程环境,利用模板参数化实现行为的组合和选择,有助于提高代码的灵活性和重用性。
所以针对性能要求高且类似于策略模式的场景下时,推荐使用Policy-based design。
背景
假设有如下需求,某个酒店拥有自己的会员等级和会员制度,普通会员没有折扣;黄金会员享受9折优惠;钻石会员享受8折优惠;如何设计这套系统。(和策略模式的需求相同)
代码实现
Policy-based design 就可以基于模板实现,也可以基于继承实现,分别如下:
基于模板的实现方式
代码语言:javascript复制#include<concepts>
#include<iostream>
template <typenameT>
concept StrategyConcept = requires(T t, float arg) {
{t.discont(arg)}-> std::same_as<float>;
};
template <typenameMemberType>
requires StrategyConcept<MemberType>
class MemberCart {
public:
float check_out(floatnum) {
MemberType t;
returnt.discont(num);
}
};
struct RegularMemberCart {
floatdiscont(floatnum) {
return num;
}
};
struct GoldenMemberCart {
floatdiscont(floatnum) {
return num * 0.9;
}
};
struct DiamondMemberCart {
floatdiscont(floatnum) {
return num * 0.8;
}
};
int using_template() {
MemberCart<RegularMemberCart> regular_cart;
std::cout<<"regular member cost "<<regular_cart.check_out(100)<<std::endl;
MemberCart<GoldenMemberCart> golden_cart;
std::cout << "golden member cost " << golden_cart.check_out(100) << std::endl;
MemberCart<DiamondMemberCart> diamond_cart;
std::cout << "golden member cost " << diamond_cart.check_out(100) << std::endl;
return 0;
}
基于继承的实现方式
代码语言:javascript复制#include<concepts>
#include<iostream>
template<typenameT>
structMemberCart:publicT
{
public:
float
};
struct RegularMemberCart {
floatdiscont(floatnum) {
return num;
}
};
struct GoldenMemberCart {
floatdiscont(floatnum) {
return num * 0.9;
}
};
struct DiamondMemberCart {
floatdiscont(floatnum) {
return num * 0.8;
}
};
int using_herb() {
MemberCart<RegularMemberCart> regular_cart;
std::cout << "regular member cost " << regular_cart.discont(100) << std::endl;
MemberCart<GoldenMemberCart> golden_cart;
std::cout << "golden member cost " << golden_cart.discont(100) << std::endl;
MemberCart<DiamondMemberCart> diamond_cart;
std::cout << "golden member cost " << diamond_cart.discont(100) << std::endl;
return 0;
}
美玉存瑕
policy-based design 根据不同的策略选择不同的行为,不仅提供了灵活性,还具有很好的扩展性。有策略模式的地方就可以有Policy-based design,但是Policy-based design也存在其固有的缺点,
- 编译器错误难以阅读和调试:当策略数量增加时,由于模板的组合爆炸性,编译器可能会生成大量的模板实例,导致编译时间显著增加,并可能产生难以理解和定位的错误信息。
- 过度专业化:如果策略被滥用,可能会导致代码过于专业化,不利于通用性的保持,有时候过度设计反而不如简单直接的设计更容易理解和维护。
- 缺乏运行时动态性:与策略模式不同,Policy-based Design在编译时就已经确定了策略,因此无法像策略模式那样在运行时动态地改变对象的行为。
总结
没有任何一种模式适用于所有场景,唯有适合的才是最好的。policy-based design虽好,切忌乱用,【当你手里拿着锤子,看什么都像是钉】不可取。