设计模式之抽象工厂模式以及与工厂模式区别

Provide an interface for creating families of related or dependent objects without specifying their concrete classes.


本篇博客属于《Java设计模式》系列之一,内容主要借鉴于 秦小波的著作《设计模式之禅》,在理解过程中可能还参考其他博主的知识,最后整理成自己的学习笔记,在此分享给大家。由于本人知识和能力有限,博客中有错误或者理解偏差的地方,还望同行及前辈们多多探讨和指点,感谢不尽。(目前本人还在实习阶段,个人认为设计模式还是要结合自己的实际经验去理解更佳,暂时更新最常见设计模式9+1篇。立个flag,将来一定会补齐)–2020.11.22

序号内容链接地址
1设计模式六大原则https://blog.csdn.net/Dawn510/article/details/109501957
2单例模式https://blog.csdn.net/Dawn510/article/details/109541109
3工厂模式https://blog.csdn.net/Dawn510/article/details/109588909
4抽象工厂模式及与工厂模式区别https://blog.csdn.net/Dawn510/article/details/109609350
5模板方法模式https://blog.csdn.net/Dawn510/article/details/109609368
6建造者模式https://blog.csdn.net/Dawn510/article/details/109609385
7代理模式https://blog.csdn.net/Dawn510/article/details/109633416
8装饰模式https://blog.csdn.net/Dawn510/article/details/109663917
9适配器模式https://blog.csdn.net/Dawn510/article/details/109962821
10观察者模式https://blog.csdn.net/Dawn510/article/details/109962858

定义

为创建一组相关或相互依赖的对象提供一个接口,而且无须指定它们的具体类。

相信挺多人第一次看到这个定义都有点懵,这都什么和什么。那么通过一个案例来了解一下。(在学习抽象工厂模式之前,一定要先理解简单工厂模式和工厂模式

举个栗子

需要一个工厂生产各种主题:白色主题、黑色主题等。

  • 白色主题的组成:白色背景、黑色的字体
  • 黑色主题的组成:黑色背景、白色的字体

给出类图:
在这里插入图片描述

  • Factory: 工厂类,定义两个抽象方法。分别是获取背景、获取字体。
  • ProductA:产品A抽象类,生产背景。
  • ProductB:产品B抽象类,生产字体。
  • ConcreteProductA1:产品A实现类,生产黑色背景。
  • ConcreteProductA2:产品A实现类,生产白色背景。
  • ConcreteProductB1:产品B实现类,生产白色字体。
  • ConcreteProductB2:产品B实现类,生产黑色字体。
  • ConcreteFactory1:工厂实现类,获取产品A1和产品B1。
  • ConcreteFactory2:工厂实现类,获取产品A2和产品B2

如此在业务代码中,实现工厂类factory1,就可以生产黑色背景和白色字体——dark主题,工厂类factory2可以生产白色背景和黑色字体——light主题。

再回到我们的定义看看:为创建一组相关或相互依赖的对象(背景和字体是相关的组件)提供一个接口(工厂类:负责生产主题),而且无须指定它们的具体类(具体类是在工厂实现类里返回具体的背景和字体,对不同工厂的实现类搭配不同的背景和字体,由此生产出各种主题)。

同样的例子还有:一个UI在三个不同平台上(Windows、Linux、macOS)上运行,会怎么设计?分别设计三套不同的应用?非也,通过抽象工厂模式屏蔽掉调操作系统对应用的影响。举其中的 弹窗Bottom和确定OK按钮为例:每种平台的弹窗和按钮都是搭配一组的,不通用。

明确需求:

  1. 产品抽象类ProductA为弹窗,具体实现类有A1,A2,A3,分别对应windows、Linux、macOS
  2. 产品抽象类ProductB为按钮,具体实现类有B1,B2,B3,同上。
  3. 工厂类生产UI,两个抽象方法分别为返回抽象类ProductA,返回抽象类ProductB
  4. 工厂类有三个实现类,继承并实现了工厂类的两个方法,工厂实现类factory1返回了A1和B1,产生了适合windows平台的UI,同理factory2、factory3.

抽象工厂模式的优点

  1. 封装性。每个产品的实现类不是高层关心的,高层关心的是接口。我们吃面包不关心面包是怎么种植,怎么运输,怎么制作。我们只知道拿着钱去超市,就能吃到面包。只需要知道工厂类,就能创造一个需要的对象
  2. 产品族内的约束为非公开。一个面包,在生产过程中黄油和面包配比为2:8。对调用工厂类的高层模块来说是透明的,不知道这个约束,他只需要一个面包早上充饥就行了。
  3. 安全性。这样不会有因为程序员昨晚加班熬夜,早上生成dark主题的时候,使用了黑色的背景,黑色的字体或者白色背景,黑色的字。

抽象工厂模式的缺点

抽象工厂模式的缺点就是产品族的扩展非常困难。如果要增加一个产品C,也就是说产品家族由原来的2个增加到3个。那么抽象工厂Factory增加一个方法getProductC(),然后两个实现类都要修改。这样违反了开闭原则,抽象类和接口是一个契约。改变契约,所有与契约有关系的代码都要修改。那这就是“有毒代码”…

抽象工厂的产品族扩展困难,但是升级很容易。什么意思呢?拿上面的主题举例,如果要每种主题添加背景音乐,工厂模式新增方法 Music getMusic(),其对应的实现方法均要修改。如果是添加一种非主流主题——红色的字体,绿色的背景。那么在ProductA的实现类新增ConcreteProductA3实现类,生成绿色背景;ProductB的实现类新增ConcreteProductB3实现类,生成红色字体;工厂实现类新增ConcreteFactory3,返回绿色背景红色字体。这样就升级了一款非主流主题。

简单工厂、工厂模式、抽象工厂小结

简单工厂

女娲造人,要一个个捏,要捏鼻子,耳朵,四肢等,还要烤到不同的肤色:白色、黑色、黄色,一步步造好一个人。但是女娲捏着发现太麻烦了,磨刀不误砍柴工,女娲造了一个阴阳炉,在炉子里刻好模板。然后用法力提供不同强度的火焰:火焰大的时候黑人,火焰小的时候白人,火焰刚好的时候黄种人就出来了。

用一个炉子可以造不同肤色的人,这就是简单工厂。具有封装的优点,不需要操心怎么实现,交给阴阳炉就好,具体实现在阴阳炉里。适合简单的场景,一个静态工厂(简单工厂也称作静态工厂,使用静态方法)直接生成需要对象

工厂方法模式

当女娲娘娘觉得世界上就只有三种人有点枯燥,于是决定增加种类,于是有中国人、韩国人、日本人、泰国人、美国人等几十种人,甚至更多。使用简单工厂,一个静态类里定义几十种甚至更多的方法不符合单一职责(应该有且只有一个原因引起类的变更)、不满足依赖倒置原则(面向接口编程:降低类之间的耦合性)。于是可以设计一个阴阳炉图纸(抽象类,目的造人),根据图纸完成各种具体炉子,每个炉子只生产一个国家的人。

定义一个用于创建对象的接口,让子类决定具体实例化哪一个类。工厂方法使一个类的实例化延迟到子类。

抽象工厂模式

简单理解抽象工厂模式是工厂模式的进一步封装。工厂模式只有一个抽象产品类,抽象工厂有着多个关联或依赖的抽象产品类。

具体点的例子:

生产一张床,工厂模式可以实现,可以创造豪华车和普通床。同样工厂模式实现生产桌子、柜子等。生产一栋房子呢,房子里有床、桌子、柜子。土豪房子里豪华床、镀金桌子、保险柜,中产房子里有普通床、四角桌、多功能柜,我家里睡木板床、破桌子、漏风柜子。

这时候抽象工厂定义三个抽象方法分别返回床、桌子、柜子。具体实现类里,土豪房工厂继承三个方法分别返回豪华床x3、镀金桌子x5、保险柜x1,中产房工厂可以返回普通床x2,四角桌x1,多功能柜x1等等…这样也防止你一不小心给我家create了一个豪华床,和我清廉的家风不搭。

工厂模式是一维坐标,要什么直接生产什么。抽象工厂模式是多维坐标(几维取决你的抽象工厂中包含几种抽象方法),房子是三维的:一个房子必须包含床、桌子、柜子。具体什么样子的床、桌子、柜子,可以在工厂实现类里指定和搭配比例。

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值