- 工厂模式说了好多年,学了好多年,也忘了好多年。
- 每次学的时候知道是怎么回事,好像明白了,工作中用的不多,过段时间又忘了。
- 这次又学了一遍,为了延长忘记的时间(不敢说为了不忘),在此记录一篇博客。
学习历程
- 由于前一段看到https://www.runoob.com上面有好多前端和各种语言的基础知识,并且以目录的形式展开,查询很方便,这次搜索工厂模式时,看到了https://www.runoob.com 的结果就直接点进来看了。就是[这篇抽象工厂模式]。(https://www.runoob.com/design-pattern/abstract-factory-pattern.html)
- 但是!读完以后,发现这篇文章讲z的抽象工厂模式居然是错的!在设计模式中哪有设计一个子类,却没办法实现父类的方法,而选择空实现的。太 ™草率了!(根据里氏替换原则:一个软件实体如果使用的是一个父类的话,那么一定适用于其子类,而且它察觉不到父类对象和子类对象的区别。然而 runoob 文章中创建的两个工厂都是只有一个方法可以被调用而另一个是空实现,就像一个瘸了左腿,一个瘸了右腿。那还抽象出一个父类有毛用啊!)
- 然而!然人惊喜的是,runoob 这篇文章下面的第一篇笔记却对工厂模式解释的非常清楚。
文章目的
- runoob 里这篇抽象工厂模式文章下面的笔记写的非常好了,我下面会拿这篇笔记做一些修改和补充。
- 补充的内容是:为什么有了简单工厂还要工厂方法,有了工厂方法还要抽象工厂,他们分别适用的条件是什么(所以这篇博客会大量借鉴上面的笔记)。
简单工厂模式
- 简单工厂模式不是 23 种里的一种,简而言之,就是有一个专门生产某个产品的类。
比如下图中的鼠标工厂,专业生产鼠标。给参数 0,生产戴尔鼠标;给参数 1,生产惠普鼠标。
笔者注:
简单工厂不是挺好的吗?通过 一个方法 和 if-else 就可以创建出不同类型的鼠标。为什么还要工厂模式(工厂方法模式)?
- 这里涉及到一个知识点,设计模式solid 原则的开闭原则(对扩展开放,但是对修改封闭”)
- 问题在于:简单工厂模式中,如果要增加华硕品牌的鼠标,就要增加一个 if-else,需要修改创建鼠标的方法。这违背了开闭原则。为了解决这个问题,就产生了工厂模式(工厂方法模式)。
工厂模式(也就是:工厂方法模式!!!)
- 工厂模式就是:鼠标工厂是个父类,有生产鼠标这个接口。戴尔鼠标工厂、惠普鼠标工厂继承它,可以分别生产戴尔鼠标、惠普鼠标。
- 生产哪种鼠标不再由参数决定,而是由创建工厂时实例化哪一个鼠标工厂决定。后续直接调用**鼠标工厂.生产鼠标()**即可
注:这里替换了原笔记中的 UML 图,因为原笔记中工厂名字叫 MouseFactory,为了方便与下面抽象工厂过渡,我自己画了一个 UML 图将其改为 PcFactory。
笔者注:
工厂模式不是挺好的吗?遵守了开闭原则,需要新建一个华硕品牌的鼠标时,创建一个华硕品牌的工厂就可以生产出华硕鼠标了。对其他部分代码没有修改。为什么还要有抽象工厂呢?
- 其实抽象工厂模式不是为了解决工厂模式的什么问题,只是针对一个工厂可以生产多个产品情况的扩展。比较一下抽象工厂模式 和工厂模式的 UML 图就知道了。
抽象工厂模式
- 抽象工厂模式也就是不仅生产鼠标,同时生产键盘。也就是 PC 厂商是个父类,有生产鼠标、生产键盘两个接口。
- 戴尔工厂、惠普工厂继承它,可以分别生产戴尔鼠标+戴尔键盘和惠普鼠标+惠普键盘。
- 创建工厂时,创建一个戴尔工厂。后续工厂.生产鼠标()则生产戴尔鼠标,工厂.生产键盘()则生产戴尔键盘。
在抽象工厂模式中,假设我们需要增加一个工厂,应该怎么办?
假设我们增加华硕工厂。则我们需要华硕工厂和戴尔工厂一样,继承 PC 厂商;之后增加华硕鼠标继承鼠标类;增加华硕键盘继承键盘类即可。
在抽象工厂模式中,假设我们需要增加一个产品,应该怎么办?
- 假设我们增加耳麦这个产品,则首先我们需要增加耳麦这个父类,再加上戴尔耳麦、惠普耳麦这两个子类。
- 之后在PC厂商这个父类中,增加生产耳麦的接口。最后在戴尔工厂、惠普工厂这两个类中,分别实现生产戴尔耳麦、惠普耳麦的功能。 以上。
笔者注:
- 从抽象工厂模式扩展一个华硕厂商很方便,只有代码的扩展,没有对原有逻辑的修改。
- 从抽象工厂模式扩展一个Mic产品却麻烦的多,需要增加Mic 产品接口,需要修改抽象工厂类和所有子工厂类。
- 总结:抽象工厂模式主要是为了解决增加工厂的问题。不是为了解决增加产品线的问题。所以增加新的工厂子类很方便,但是增加产品线改动比较大。(这个没辙,这就是抽象工厂的缺点。)
扩展资料
- 知乎这一篇讲抽象工厂和工厂方法的的文章也挺好的,我最早就是看这文章理解工厂模式的,虽然看完没多久又陷入了恍惚。
- 抽象工厂模式在实际使用场景下,还是有优化空间的,可以不用每次修改工厂时,都把创建工厂( new DellFactory() )的地方改个遍,因为只会选择某一个工厂创建实例,所以可以结合简单工厂模式来创建具体的工厂。空口说起来有些不形象,详细内容大家可以看《大话设计模式》。从第 15 章-抽象工厂模式 的 15.6 小节开始往后看到 15 章结束。如果《大话设计模式》这本书不想买,可以点击下载这个 PDF(码:d5nn)看看。