多态的设计

cpp 多态是一个在搭建模板、架构、简化流程等时候经常使用的设计。

下面举例说明它在架构搭建时的作用:

题目:
需要设计一个流水线程序,整个流水线上的子操作(Action)的个数和内容都是要根据具体情况分析的或者经常发生变动,在这种情况下,如何设计一个较为合理架构,每次添加删除子操作(Action)带来的变动很小化。

  首先解释下为什么要设计一个架构,对于这样一个流水线的需求,他的总体结构是确定的(就是一个一个子操作逐步执行),但是他的细节(子操作的具体内容)又是变化很大的,如果每次变动,都要重新写一个程序的话,很多在搭建结构上的操作每次都要重写一遍,这样很浪费时间,而且只要是有人为的参与,就有一定程度上出错的可能性。所以架构的出现就是为了避免重复的不必要的工作,使得程序员能够更加关注于业务逻辑设计的本身。

该题目要求的架构实际是一个很简单的设计,思路如下:
1. 为子操作设计一个基类 Action,定义规范,同时提供虚函数作为实现子类具体操作的接口
2. 创建一个存放子操作的容器,actions
3. 实现具体的子操作,添加到 actions 中
4. 逐个容器中取出子操作,并利用多态执行子操作

每次子操作发生变化,或要增删子操作时,只需要修改第二步骤,其他的都无需改变。

实现具体子操作就是继承子操作的基类,实现它的虚函数;甚至如果每个子操作很多步骤都是固定的,只是某几个特定的步骤需要修改,还可以在基类中实现这些固定的步骤作为默认值,这样具体的子操作只需要重写部分需要修改的步骤对应的虚函数即可。

注意:如果在基类的构造函数里调用多态函数(virtual),只会调用基类的相应函数,而不会调用子类重写的多态函数,因此无法表现出多态特性,这是因为在执行父类的构造函数或析构函数时,执行者是父类对象,而不是子类对象。

下面是具体的代码实现:

#include <iostream>
#include <vector>

using namespace std;

class Action {
public:
    Action(){
        // 不要在构造函数里面使用多态函数,否则多态的特性无法呈现,如果调用的是纯虚函数时,还会在运行时报错
        // 这是因为在执行父类的构造函数或析构函数时,执行者是父类对象,而不是子类对象
        start(); // 写在这里没有调用子类重写的多态函数
    }

    void start(){
        cout << "first step" << endl;
        doFirstStep();
        cout << "last step" << endl;
        doLastStep();
    }
protected:
    virtual void doFirstStep(){
        cout << "default first step" << endl;
    }
    virtual void doLastStep(){
        cout << "default second step" << endl;
    }
};

class MoveAction : public Action{
protected:
    // 只修改第一个步骤,第二个步骤使用默认的(父类中的)
    virtual void doFirstStep(){
        cout << "running" << endl;
    }
};

class MLAction: public Action{
protected:
    virtual void doFirstStep() override{
        cout << "training" << endl;
    }

    virtual void doLastStep() override{
        cout << "testing" << endl;
    }
};

void startAllAction(vector<Action*> actions){
    for(unsigned int i = 0; i < actions.size(); i++){
        actions.at(i)->start();
    }
}

int main() {
    vector<Action*> actions;
    cout << "invoke constructor state----------------------------" << endl;
    actions.push_back(new MoveAction());
    actions.push_back(new MLAction());

    cout << "invoke start state ---------------------------------" << endl;
    startAllAction(actions);
}

我们组某个项目中的pipeline和action就是基于这种思想设计的。
项目位置: https://github.com/tempflying/dji/tree/master/v3/flightControl/DJI3OnBoardModel

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值