c++行为型设计模式:策略模式

设计模式往往是类库设计者需要着重考虑的事情,GoF著作中提出的很多种类的设计模式,但是仔细阅读下来,大部分的设计模式在语法层面上就是灵活使用多态,而且,会发现好多设计模式只是名称不一样,但是语法上很多相似的。这个系列也仅仅是对学习和工作过程中的一些设计方法的简单的个人总结,会参杂一些个人认知。
场景:
客户端(软件应用开发人员)需要对数据进行加法和减法的操作,但是公司没有一个这样的库,因此类库开发人员进行了如下操作:新建了math文件,里面有加法、减法这两种算法(姑且认为是很厉害的算法),库的设计人员一开始将这两种算法作为全局函数的形式放在了namespace中。
namespace math
{
int add(int a,int b);
int sub(int a,int b);
}
所以客户端使用math库时,就直接使用加法或减法操作函数就行。进一步的,客户端想要个乘法算法,设计人员在库函数中添加相应的算法,客户端再在代码中添加multiplication函数。为了避免客户端那边频繁的增、删、改等操作。设计人员就更进一步进行抽象,有一个mathOperation(int a,int b,T func)模板函数,这个函数可以这样被使用:
mathOperation(1,2,add<int,int>{})亦或mathOperation(2.0f ,1.0f,sub<float,float>{})亦或mathOperation(int a,int b,[&](){})。之前的算法也暂时保留,直到客户端那边把之前的代码重构,全部替换为mathOperation后,math库v2版就发布了。这里已经开始有策略的思想了。这种设计也足够应付大部分的场景了。
客户端某天需要更复杂的矩阵计算时,设计人员就要开始考虑将类结构了。

点击查看伪代码
strcut data
{
int a;
int b;
int c;
...
};

struct mathOperation
{
virtual void assemble(data& d){}; //对传入的数据进行组装成一个矩阵
virtual void optimization(){};//为了高效并行的计算,对矩阵进行优化
virtual bool done(){};// 正式计算,可能收敛也可能不收敛
};

struct symmetric : public mathOperation //处理对称矩阵
{
void assemble(data& d) override {};
void optimization() override {};
bool done() override {};
};

struct asymmetric : public mathOperation //处理非对称矩阵
{
void assemble(data& d) override {};
void optimization() override {};
bool done() override {};
}

enum class matrixFormat
{
symmetricMatrix,
asymmetricMatrix,
...//还存在其他各种复杂形式
}

class matrixProcess
{
public:
void setMathOperation(const matrixFormat format)
{
  switch(format)
  {
  case format::symmetricMatrix:
    mathOperation_ = std::make_unnique<symmetric>;
    break;
  case format::asymmetricMatrix:
    mathOperation_ = std::make_unnique<asymmetric>;
    break;
  }
}
void process(data& d)
{
  mathOperation_->assemble(d);
  mathOperation_->optimization();
  if(mathOperation_->done)
   {
   }
}

private:
std::unique_ptr<mathOperation> mathOperation_;
};

int main()
{
matrixProcess mp;
mp.setMathOperation(format::symmetricMatrix);
mp.process(...);
return 0;
}

上述代码就是类库设计人员利用策略模式设计出的矩阵计算库(这里就不画UML图了,主要是我懒)。其实这个模式我个人看来就是处理这样的场景: 在开发某个功能时,处理这个功能的流程是固定的(通用框架),具体实现是在其他地方实现的。语法设计层面上其实有很多的实现方式。有人或许有疑问,假如这些矩阵子类改成函数都放在matrixProcess类中,貌似也可以也可以满足客户端的需求呀,其实真正实际开发中,假如使用这种方式的话,可能会存在很多的if elseif 判断,在c++的开发过程中,大量的if elseif 并不是好的实践。上述代码只是策略模式实现方式的一种,核心内容就是有个基类(难点就是如何抽象出一个基类),然后根据不同的场景实现不同的子类。****然后这个把这个基类作为成员变量,以组合的方式与上层的类相结合****。就是抽象出基类,子类实现,利用动态多态性质,在运行时去实现业务。设计模式玩来玩去其实就是围绕着这些。但c++中的设计模式还有一个更好玩的地方是静态多态。这里的策略模式也可以用静态多态的方式(上模板,去掉枚举)。还有一个有意思的点是,假如把策略模式中的组合的方式换成继承的方式,那又换了另一个叫法,叫模板方法模式。回到本文开始说的那些。设计模式名称是次要的,主要的是抽象的思路和解耦的思路。
posted @ 2024-06-18 09:43  tian52  阅读(16)  评论(0)    收藏  举报