文章目录
前言
开篇词
博客有一阵子没写了,中间接了个测评的活,做了简单的入门。
主要还是工作繁忙,入职新的工作之后,对于公司框架的不熟悉导致自己进度缓慢,最近几个月其实都在忙着公司学习框架以及加班。累是有点的,不过对于设计模式以及UML之类的,收获很大。当然生活不止这样,期间也学了些摄影以及出游视频拍摄剪辑之类的,外加骑行杂七杂八的…反正人的精力是有限的。
话题回归,前段时间把 《大话设计模式》 《大话设计模式》 《大话设计模式》这本书看完了,这篇专栏就考虑结合这本书,加上自己的理解,回顾一下自己的设计模式,写一点学习笔记。
作为初级程序员,目前写的博客属于这个阶段的理解,若干年后再回首,可能会有不一样的想法。博主水平有限,所以写的这种类型的专栏只是作为自己的一个思考回顾和笔记为主,如有错误,评论指正。
个人对设计模式的理解
相比于之前写C,或者嵌入式的C++代码。软件开发的时候,更注重的是面向对象设计。
前段时间我经常把业务代码和逻辑代码混在一个函数里面,同时功能之间的耦合很紧密(这个说起来有点文绉绉的)。
说白了就是:我把UI,业务(就是一些操作数据接口之类的),资源分配与释放之类的全部放到一个函数里去做。
我后面要改UI,改操作,加功能,全部在这个函数,或者这个类里面进行操作,任何的改动都需要在这个类中进行处理,这就是耦合紧密,而且维护起来很麻烦。
设计模式的出现就是为了解决这个问题。面向对象的设计,就是为了降低耦合,功能模块化,可复用。
将类与类之间的依赖通过接口进行依赖倒置,即A依赖B的一些数据,现在通过C接口。A向C接口拿B数据,B向C接口拿A操作。
这样A不管B里面有什么,只管问C就行了。B里面怎么改变其实影响不到A。
总而言之,设计模式就是降低耦合,提高复用,便于多人协同开发,便于维护与拓展的一种设计思路。
简单工厂模式
1.举例
书中是举了个计算器的例子,我这里就举一个自己遇到的例子。
现在有这样一个需求,需要将软件的采集数据按照文本,图片两种方式进行导出。
简单分析一下,功能操作就是导出数据,如果是文本类型,导出文本,如果是图片类型,导出图片。
那么这个数据类型就是我们要考虑因素。
伪代码1:
void exportData(const std::string &type) { if(type=="text") { //导出文本 .... } if(type=="image") { //导出图片 .... } }
上面这份代码,我们可以看到不同类型执行不同的操作。虽然非常直观,并且可以解决问题,但是这个是面向过程。
如果我想要拓展,我想增加一个表格格式呢?if(type=="table")"
在这个函数里加?那继续添加各种客户想要的自定义格式呢?一直加吗?如果对导出文本功能的时候,我还想执行一些别的操作,全部 在这个exportData函数里面加吗?这就耦合很深了。
既然是面向对象的设计,我们得有类——对象的概念。
2 面向过程->面向对象
我们把ExportOperation理解为一个导出操作接口,这个接口可以导出文本数据和图片数据。后面可以拓展,比如导出成表格。
导出文本数据其实是导出文本对象做导出操作,导出图片数据其实是导出图片对象做导出操作。
那文本导出对象和图片导出对象对于ExportOperation对象来说其实是他的子类。
就是下图左半部分的一个理解。
接下来考虑对象的实例化,我们导出文本和数据,其实需要的是ExportText和ExportImage的操作,那我们其实导出操作的时候,对于UI界面展示或者说日常使用,一般就是一个导出操作的按钮。谁管你是导出什么?我只需要导出就行了。
所以这个实例化不好直接创建是文本的还是图片的,只能创建一个ExportOperation这种最外层的。
一开始我们根据类型导出,这里我们可以根据类型来创建具体的对象。
也就是如果类型是text创建ExportText对象,如果类型是image创建ExportImage对象。
写到这可能会疑惑,这个ExportFactory是干嘛用的??好像只要左半边就可以了。
3.工厂的意义
书中原话是这样写的,这里开根什么的是书中计算器的例子。
到底要实例化谁,将来会不会增加实例化的对象,比如增加开根运算,这是很容易变化的地方,应该考虑用一个单独的类来做这个创造实例的过程,这就是工厂。
我们看上面的UML类图,可以发现其实这个工厂本身的作用其实就是根据类型创建一个对应的导出操作实体对象。它是用来负责创造实例的一个工厂。通过这个工厂的createExportOperation函数,我们创建实例的过程其实就不直接对里面的类进行操作了,相当于做了一层封装。面向对象三大特性:继承,多态,封装。
下面是伪代码
class ExportOperation { public: virtual void exportData() {}; }; class ExportText :public ExportOperation { public: void exportData() override; }; class ExportImage :public ExportOperation { public: void exportData() override; }; enum OperationType { text = 1, image }; class ExportFactory { public: static ExportOperation* createExportOperation(OperationType type) { ExportOperation* Operation; switch (type) { case text: { Operation = new ExportText(); break; } case image: { Operation = new ExportImage(); break; } default: return nullptr; } }; };
在别的函数中可以直接调用ExportFactory::createExportOperation
。
总结
这篇博客写了一下自己对于设计模式的理解,同时复习回顾了一下简单工厂模式。
结合自己在项目中遇到的问题,做了一下简单的举例,并从面向过程到面向对象的一个转变,做了一个回顾与记录。