C++|多模式统一管理实战

65 阅读5分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第8天,点击查看活动详情

在有些情况下,软件在不同应用场景会展示不同的功能以及效果。

比如说:在A应用环境下,展示A画面;到B应用环境下,本应该展示A画面的地方,需要更换成B画面。但是该软件的具体逻辑以及业务都未曾发生变化。

在这时,因为变动较小,不值当重新开发,采用了复用资源技术,只需要在原有适用于A环境的基础上扩充一个适应B环境的结构,不仅可以降低一个系统的成本,并且可以改进系统的质量(这也是我们在学习高级架构师中需要掌握的知识)

对此需求,我们该使用何种方式改进呢?

首先,需要明白在A应用环境与B应用环境中,只有有些特定的页面是需要变动,其它功能全都不需要变动的。

其次,可以将不共用的部分提出出来,这里采用了工厂模式。

最后,分标识运行程序。

什么叫做工厂模式?

定义:定义一个创建对象的接口,让其子类自己决定实例化哪一个工厂类。

图片.png

优点

1:没有了将应用程序类绑定到代码中的要求,代码只处理接口,因此可以使用任何实现了接口的类;

2:允许子类提供对象的扩展版本,因为在类中创建对象比直接在客户端创建要更加灵活;

3:典型的解耦框架。高层次模块只需要知道产品的抽象类,无需关心其他实现类,满足迪米特法则、依赖倒置原则和里氏替换原则。

缺点

1:类的个数容易过多,增加复杂度。

2:增加了系统的抽象性和理解难度。

3:抽象产品只能生产一种产品,此弊端可使用抽象工厂模式解决。

说了这么多抽象语言,接下来,我来讲述下在实战中是如何应用的吧!

实战应用

1:定义区分标识

因为应用的环境或者是场景不同,我们要对其进行区分,在程序中我们可以采用枚举的方式。

enum ENUM_RunningFlag
{
    RunningFlag_A,
    RunningFlag_B
}

上述标明了两种运行模式,A模式以及B模式。在程序一开始运行时就需要进行设置,保证了标识的唯一性以及可控性。

那么,对于这两种状态,我们如何设置比较方便呢?

最简单的方式,写一个ini的配置文件,在配置文件中进行区分,最小程序减少了代码修改。并且我们要保证读取配置文件得唯一性,也就是说,只有一个地方可以控制配置文件的读写操作。

2:使用设计模式搭建框架

这也是我们实现的重中之重了。

2.1:定义工厂基类

假设基类名称:QBasicProcessingWidget

所有的子类都需要继承当前类,并且对外操作的类也是该类。

确保了对外接口统一,只是内部实现以及操作不同,体现了上述说的工厂模式的优点以及便捷之处了。

示例如下:

class QBasicProcessingWidget:public QWidget
{
public:
    QBasicProcessingWidget();
    virtual ~QBasicProcessingWidget();
public: //对外开放统一接口
    virtual void setData(int ndata) = 0; //设置数据
}

代码讲解:

基类中定义了一个基函数(setData),当继承于该类时,同时也需要实现该函数的方法。根据不同的功能需求做特殊的处理。

2.2:子类实现

假设子类名称:QProcessingWidgetA

该类用于实现A环境展示页面。

示例如下:

class QProcessingWidgetA:public QBasicProcessingWidget
{
public:
    QProcessingWidgetA();
    virtual ~QProcessingWidgetA();
public: //公共函数处理
    virtual void setData(int ndata);
public://特殊函数处理
    void SetMode(int nMode); //设置当前模式
}

2.3:对外操作工厂类实现

根据项目应用的场景不同,对应选取的子类也是各不相同的,为了确保统一处理,我们对外访问以及开放的都是所有子类的父类。

对此,需要设定一个工厂类,用于实现子类的创建以及接口访问。

示例如下:

class CProcessingFactory
{
public:
    CProcessingFactory();
    ~CProcessingFactory();
public: //对外操作接口
    QBasicProcessingWidget* CreateProcessingWidget(ENUM_RunningFlag enumType, QWidget* parent);
}

代码讲解

当前类并没有任何实际意义,只作为一个中间载体,方便我们操作子类而已。

根据参数enumType的不同标识,创建不同的操作子类。

QBasicProcessingWidget* CProcessingFactory::CreateProcessingWidget(ENUM_RunningFlag enumType, QWidget* parent)
{
    QBasicProcessingWidget *pWidget = nullptr;
    if(enumType == RunningFlag_A)
    {
        //创建A环境的子类
        pWidget = QProcessingWidgetA(parent);
    }
    else if(enumType == RunningFlag_B)
    {
        //创建B环境的子类
    }
    return pWidget; //返回操作类指针
}

3:具体应用

框架搭建完成后,接下来就是在代码中实现具体功能了。

3.1:创建类

首先,我们需要先将工厂类创建出来

CProcessingFactory *pFactory = new CProcessingFactory();

其次,创建实际应用类

QBasicProcessingWidget *dlg = pFactory->CreateProcessingWidget(RunningFlag_A, this);
dlg->show();

3.2:特定类函数操作

根据枚举类型的不同已经知道了如何创建子类,那么该如何从特定的子类中获取数据呢?

QProcessingWidgetA *pWidgetA = (QProcessingWidgetA)dlg;
pWidgetA->setMode(1); //上面A子类中的特殊函数设置

直接转换就可以了,是不是很简单?

到这里,对于多模式的统一管理,具体的代码思路逻辑已经讲解完成了。只要框架搭的好,再来上十几个子类也不是问题,代码应用不是重点,重点是学习的思路以及设计。

我是中国好公民st,一名C++开发程序猿~