本文主要讲解设计模式中的三类工厂模式:
- 简单工厂模式(Simple Factory Pattern)
- 工厂方法模式(Factory Method Pattern)
- 抽象工厂模式(Abstract Factory Pattern)
1 简单工厂模式
图例分析:
考虑一个简单的应用场景,这个应用场景可以提供很多形状(比如图中的Circle、Square、Rectangle),它们都源于一个Shape接口(也可以理解为基类),Circle、Square、Rectangle都实现了此接口。
go 语言没有构造函数一说,所以一般会定义NewXXX函数来初始化相关类。 NewXXX 函数返回接口时就是简单工厂模式,也就是说Golang的一般推荐做法就是简单工厂。
2 工厂方法模式
工厂方法模式:定义一个用于创建对象的接口,让子类决定实例化那一个类,工厂方法使一个类的实例化延迟到其子类。
图例说明:
定义了两个接口Shape和ShapeFactory,Circle、Square、Rectangle和CircleFactory、SquareFactory、RetcangleFactory分别实现了Shape和ShapeFactory接口。Demo中创建了ShapeFactory接口,让CircleFactory、SquareFactory、RetcangleFactory决定去实例化哪类Shape。
优点:
- 在工厂方法模式中,工厂方法用来创建客户所需要的产品,同时还向客户隐藏了哪种具体产品类将被实例化这一细节,用户只需要关心所需产品对应的工厂,无须关心创建细节,甚至无须知道具体产品类的类名。
- 基于工厂角色和产品角色的多态性设计是工厂方法模式的关键。它能够使工厂可以自主确定创建何种产品对象,而如何创建这个对象的细节则完全封装在具体工厂内部。工厂方法模式之所以又被称为多态工厂模式,是因为所有的具体工厂类都具有同一抽象父类。
- 使用工厂方法模式的另一个优点是在系统中加入新产品时,无须修改抽象工厂和抽象产品提供的接口,无须修改客户端,也无须修改其他的具体工厂和具体产品,而只要添加一个具体工厂和具体产品就可以了。这样,系统的可扩展性也就变得非常好,完全符合“开闭原则”。
缺点:
- 在添加新产品时,需要编写新的具体产品类,而且还要提供与之对应的具体工厂类,系统中类的个数将成对增加,在一定程度上增加了系统的复杂度,有更多的类需要编译和运行,会给系统带来一些额外的开销。
- 由于考虑到系统的可扩展性,需要引入抽象层,在客户端代码中均使用抽象层进行定义,增加了系统的抽象性和理解难度。
3 抽象工厂模式
抽象工厂模式:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
图例说明:
定义了三个接口Television、Fridge、Factory,XiaoMiTelevision、HaiErTelevision和XiaoMiFridge、HaiErFridge以及XiaoMiFactory、HaiErFactory分别实现了它们。Demo中定义了Factory,使用XiaoMiFactory、HaiErFactory分别生产Television或Fridge。
为了更清晰地理解工厂方法模式和抽象工厂模式的区别,需要引入两个概念:
- 产品等级结构:不同品牌的同一类产品,比如电视机,其子类有海尔电视机、TCL电视机等,电视机与具体品牌的电视机之间就构成了一个产品等级结构。
- 产品族:是指同一个工厂生产的,位于不同产品等级结构中的一组产品。比如海尔电器厂生产的海尔电视机、海尔电冰箱等。海尔电视机位于电视机产品等级结构中,海尔电冰箱位于电冰箱产品等级结构中。
因此可以总结为以下几点:
- 当系统所提供的工厂所需生产的具体产品并不是一个简单的对象,而是多个位于不同产品等级结构中属于不同类型的具体产品时需要使用抽象工厂模式。
- 抽象工厂模式是所有形式的工厂模式中最为抽象和最具一般性的一种形态。
- 抽象工厂模式与工厂方法模式最大的区别在于,工厂方法模式针对的是一个产品等级结构,而抽象工厂模式则需要面对多个产品等级结构,一个工厂等级结构可以负责多个不同产品等级结构中的产品对象的创建 。当一个工厂等级结构可以创建出分属于不同产品等级结构的一个产品族中的所有对象时,抽象工厂模式比工厂方法模式更为简单、有效率。
优劣势:
抽象工厂模式在横向切换中表现优异,比如从XiaoMiFactory切换为HaiErFactory,但是在纵向扩展时,改动的地方就比较多了,比如需要增加Telephone产品时,就需要增加Telephone接口和XiaoMiTelephon以及HaiErTelephone,并且还需要修改Factory和XiaoMiFactory以及HaiErFactory。
改造:
可以使用 简单工厂模式+配置文件 对抽象工厂模式进行改造。这里留给读者自己思考吧