一、工厂模式的由来
二、简单工厂模式
例子:创建一个ICourse课程接口:
创建一个JavaCourse实现类:
创建一个PythonCourse实现类:
创建一个CourseFactory类,用来生成JavaCourse或PythonCourse对象:
创建一个SimpleFactoryTest测试类,来看客户端调用:
类关系结构图:
1、简单工厂模式(Simple Factory Pattern):指由一个工厂对象决定创建出哪一种产品类的实例。(属于创建型模式,但它不属于GOF(四位作者)的23种设计模式之一)
2、目的:减少代码冗余程度,提高代码的复用性。
3、适用场景
- 工厂类负责创建的对象较少
- 客户端只需要传入工厂类的参数,对于如何创建对象的逻辑不需要关心
4、优点:只需传入一个正确的参数,就可以获取你所需要的对象,无需知道其创建的细节。
5、缺点
- 工厂类的职责相对过重,增加新的产品时,如果产品存在差异化的逻辑,则需要修改工厂类的判断逻辑,违背开闭原则
- 不易于扩展过于复杂的产品结构
三、工厂方法模式
(简单工厂模式的升级版)
例子:创建一个ICourseFactory接口,也可以是抽象类(超级工厂):
创建一个JavaCourseFactory工厂实现类,用来生成JavaCourse对象:
创建一个JavaCourseFactory工厂实现类,用来生成PythonCourse对象:
创建一个FactoryMethodTest测试类,来看客户端调用:
类结构关系图:
1、工厂方法模式(Factory Method Pattern):指定义一个创建对象的工厂接口,但让实现这个接口的工厂类来决定实例化哪个类,工厂方法模式让类的实例化推迟到子类中进行。(属于创建型模式)
2、目的:解决创建多个产品的职责问题,遵循开闭原则、单一职责原则。(不同的产品,用不同的工厂来创建,即不同的工厂负责不同产品差异化的创建逻辑)
3、适用场景
- 创建对象需要大量重复的代码(超级工厂可以定义为抽象类,把公共的逻辑放在该类的非抽象方法中,让子类在实现抽象方法的同时还可以调用父类的非抽象方法,提高代码的复用性)
- 客户端(应用层)不依赖于产品类实例如何被创建、实现等细节
- 一个类通过其子类来指定创建哪个对象
4、优点
- 用户只需关系所需产品对应的工厂,无需关心创建细节
- 加入新产品符合开闭原则,提高了系统的可扩展性
5、缺点
- 类的个数容易过多,增加了代码结构的复杂度
- 增加了系统的抽象性和理解难度
四、抽象工厂模式
(方法工厂模式的升级版,不遵循开闭原则,但易于扩展。每种设计模式都有其优缺点,不能因为它不符合开闭原则就不使用,要结合业务场景)
讲解抽象工厂之前,先了解两个概念:产品等级结构、产品族。
从上图中可以看出有正方形、圆形和菱形三种图形,相同颜色深浅的就表示同一个产品族,相同形状的代表同一个产品等级结构。同样可以从生活中来举例,比如美的电器生产多种家用电器。那么上图中,颜色最深的正方形可以代表美的洗衣机、颜色最深的圆形代表美的空调、颜色最深的菱形代表美的热水器,颜色最深的一排都属于美的品牌,都是美的电器这个产品族。再看最右侧的菱形,颜色最深的既然代表了美的热水器,那么第二排颜色稍浅的菱形代表海尔热水器。同理,同一产品结构下还有格力热水器、格力空调、格力洗衣机。
再看下面这张图,最左侧的小房子我们就认为具体的工厂,有美的工厂、海尔工厂、格力工厂。每个品牌的工厂都生产洗衣机、热水器和空调。
例子:创建一个ICourseFactory接口或抽象类:
创建两个产品接口INote、IVideo:
创建两个实现类JavaNote、JavaVideo:
创建一个JavaCourseFactory类:
创建一个JavaCourseFactory类:
创建一个AbstractFactoryTest测试类,来看客户端调用:
类关系结构图:
1、抽象工厂模式(Abstract Factory Pattern):指提供一个创建一系列相关或相互依赖对象的接口,无需指定他们具体的类。(属于创建型模式)
2、目的:解决更加复杂的业务场景。
3、适用场景
- 客户端(应用层)不依赖于产品类实例如何被创建、实现等细节
- 强调一系列相关的产品对象(属于同一产品族)一起使用创建对象需要大量重复的代码
- 提供一个产品类的库,所有的产品以同样的接口出现,从而使客户端不依赖于具体实现
4、优点
- 具体产品在应用层代码隔离,无需关心创建细节(遵循单一职责原则)
- 将一个系列的产品族统一到一起创建
5、缺点
- 规定了所有可能被创建的产品集合,产品族中扩展新的产品困难,需要修改抽象工厂的接口
- 增加了系统的抽象性和理解难度