策略模式虽好,Policy-based design更佳

2024-07-18 13:21:39 浏览数 (3)

策略模式(设计模式——策略模式)大家耳熟能详,简言之,策略模式基于运虚表指针实现多态,但运行时的多态是有时间成本的。对于性能要求高的场景,策略模式反而不是最优选择。

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虽好,切忌乱用,【当你手里拿着锤子,看什么都像是钉】不可取。

1 人点赞