持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第8天,点击查看活动详情
在有些情况下,软件在不同应用场景会展示不同的功能以及效果。
比如说:在A应用环境下,展示A画面;到B应用环境下,本应该展示A画面的地方,需要更换成B画面。但是该软件的具体逻辑以及业务都未曾发生变化。
在这时,因为变动较小,不值当重新开发,采用了复用资源技术,只需要在原有适用于A环境的基础上扩充一个适应B环境的结构,不仅可以降低一个系统的成本,并且可以改进系统的质量(这也是我们在学习高级架构师中需要掌握的知识)
对此需求,我们该使用何种方式改进呢?
首先,需要明白在A应用环境与B应用环境中,只有有些特定的页面是需要变动,其它功能全都不需要变动的。
其次,可以将不共用的部分提出出来,这里采用了工厂模式。
最后,分标识运行程序。
什么叫做工厂模式?
定义:定义一个创建对象的接口,让其子类自己决定实例化哪一个工厂类。
优点:
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++开发程序猿~