我是老温,一名热爱学习的嵌入式工程师 关注我,一起变得更加优秀! 1 - 什么是抽象工厂模式? 前面两篇文章,讲述了工厂模式里面的两种:简单工厂模式和工厂方法模式,这两种设计模式都有其各自的优缺点和适用场景。 本篇文章继续讲述最后一种工厂模式,抽象工厂模式。(Abstract Factory Pattern) 抽象工厂模式,是一种为访问类提供一个创建一组相关或相互依赖对象的接口,而且访问类无需指定所要产品的具体类就能够得到同族产品不同等级的产品的模式结构。 如同前面两种工厂模式说的那样,你是一家工厂的CEO,刚刚起家的时候,只有一间工厂(简单工厂模式)根据季节的不同,而生产不同的产品。 后来你赚翻了,干脆建起不同的工厂(工厂方法模式)来生产不同的产品。 然后发展到今天,干脆搞起自己的工程建筑团队,自己搞定工厂的建设,喜欢建什么工厂就建什么工厂(抽象工厂模式)。 比如,A工厂,它不仅仅生产LCD,它还生产跟LCD一起配套的触摸板,然后组装成一个触摸显示模块,B工厂也是一样的道理。 那么,A工厂的LCD和触摸板,组成了同一个公司内的产品族,而A工厂的触摸板和B工厂的触摸板,就是不同公司的同一个产品等级。 通俗来说就是,抽象工厂模式主要是对工厂进行进一步的抽象,也就是说这家“抽象出来的工厂”是用来生产“工厂”的,它不生产具体的产品, 具体的产品由它生产出来的“产品工厂”完成,并且,“产品工厂”不仅仅只生产一种产品,还生产多种产品。 而A工厂和B工厂,是由抽象工厂进行构建的,也就是说,在抽象工厂方法里面,会有A工厂和B工厂的抽象,会有同一个产品等级的抽象,也会有同一个产品族的抽象。 2 – 什么情况下要用抽象工厂模式? 在工厂方法模式里面, 一个产品系列就对应了一个工厂类,如LCD产品对应lcd_factory,如果再新增一个产品系列,比如新增一个touch产品,就需要新增加与该产品对应的工厂类touch_factory。 而在抽象工厂模式里面,是由一个工厂类构建多个不同类型的产品,比如,a_factory既可以构建LCD产品,也可以构建touch产品。 对于这类情景,比如:LCD要和触摸板绑定,形成一个触摸屏模组,这个触摸屏模组分别由不同的供应商来提供, 比如,A公司提供适配好的触摸屏模组(包含LCD和触摸板),并且与B公司提供的触摸屏模组不兼容,但我们在应用层的时候,要同时适配A公司和B公司提供的触摸屏模组,这个时候就可以用到抽象工厂模式。 因为我们在应用层设计的时候,是尽量不关心模组本身的初始化以及具体的操作,我们是希望在应用层中,使用同一个接口去适配不同厂家提供的触摸屏模组。 3 – 如何使用抽象工厂模式? 具体的情景:比如有两家工厂,A工厂和B工厂,它们同时拥有生产LCD和Touch触摸板的能力,并且,A工厂生产的LCD只能跟A工厂生产的Touch触摸板进行适配,A和B两间工厂的产品,是不能相互适配的。 那么在软件设计的时候,需要对LCD产品和Touch触摸板产品进行抽象(分别声明一个结构体,如:struct lcd 和struct touch),还要对A、B两家工厂的生产能力进行抽象,比如声明结构体 struct lcd_touch_abstract_factory。 1、先创建两个头文件,用来声明struct lcd 和 struct touch 这两种类型的产品,表示对这两种产品进行具体抽象,注意,这只是一种产品的抽象,并不是具体产品的实例,为了简洁表达,这两个结构体只实现了简单的打印功能,具体的代码如下图所示。 2、然后再创建关于抽象工厂的结构体struct lcd_touch_abstract_factory,这个结构体表示一家抽象的工厂,注意,这只是工厂的抽象,不是工厂的实例,需要用这个结构体定义结构体变量,才能算是工厂的实例,代码如下图所示。 3、有了LCD和触摸板Touch这两款产品的具体抽象,那么就可以为这两家工厂生产出来的产品分别进行具体实例化,也就是,对于A工厂的LCD和触摸板Touch,需要有对应的产品a_lcd和a_touch,B工厂也是同样的道理,代码如下图所示。 4、以A工厂生产的a_lcd为例,在a_lcd.h里面,主要声明了一个a_lcd类,这个类继承自lcd.h里面的父类,并且提供构造函数和析构函数,来进行a_lcd这款产品的创建和销毁,a_lcd.h的代码,如下图所示。 5、在a_lcd.c这个文件里面,主要是对构造函数和析构函数的具体实现,还有就是实现了a_lcd这款产品的具体功能,这里只实现了一个简单的打印功能,具体的代码如下图所示。 6、对于A工厂生产的a_touch产品,以及对于B工厂生产的b_lcd和b_touch,也是同样的道理,可以用同样的思路进行举一反三的理解,这里限于篇幅,就不列出a_touch,b_lcd,b_touch的具体代码了。 7、虽然有了具体的产品实例(a_lcd、a_touch、b_lcd、b_touch),也需要有具体的工厂实例,才能对产品进行构建,前面已经对工厂进行了抽象,那么,可以基于前面的工厂抽象,创建a_factory和b_factory这两家工厂实例,如下图所示。 8、以A工厂的实例a_factory进行分析(B工厂可以举一反三),先创建一个a_factory.h头文件,在里面声明一个结构体struct a_factory,这个结构体继承自前面的抽象工厂lcd_touch_abstract_factory_t,并提供A工厂的构造函数和析构函数,如下图所示。 9、在a_factory.c文件里面,是对工厂的产品制造能力的具体实现(因为抽象工厂类里面,对这些能力进行了封装),比如,创建LCD和销毁LCD,创建触摸板Touch和销毁触摸板Touch,然后在工厂的构造函数和析构函数里面,分别初始化工厂抽象类的接口。 10、至此,关于抽象工厂模式里面的四个角色:抽象的工厂,具体的工厂,抽象的产品,具体的产品,都已经全部实现,具体的逻辑关系,可以仔细阅读源码。 11、在业务应用层的代码,我们只需要使用A工厂和B工厂的构造函数,创建出一个具体的工厂,然后把创建出来的具体工厂,赋值给通用的工厂模型,后面的一系列操作,都可以基于这个通用的工厂模型。