什么是抽象工厂模式
抽象工厂模式(Abstract Factory Pattern) 是一种比较常见的设计模式,其定义如下:Provide an interface for creating families of realted or dependent objects without specifying their concrete classes.(为创建一组相关或相互依赖的对象提供一个接口,而且无须指定它们的具体类)
抽象:其实就是指定某一个接口的规范,具体点来说,也就是创建一个基类,基类遵守着某一套规范,但是具体的实现规则让子类来完成。当然指定接口的规范,我们也可以使用协议。
抽象工厂的通用类图
由上图可知,抽象工厂由一个产品抽象类(当然也可以是多个)、一个抽象工厂类、多个具体产品子类、多个具体工厂类组成。当多个产品抽象类中由相同类型的子类的时候,就可以使用抽象工厂模式,参与者的角色:
抽象工厂角色:负责创建抽象产品,指定需要的接口,任何在模式中创建对象的工厂都必须实现这个接口
具体工厂角色:实现抽象工厂接口的具体实现类,直接在客户端的使用下创建对应的产品实例。
抽象产品角色:工厂方法所创建产品对象的超类型,也就是产品对象共同的父类或者共同的接口
具体产品角色:是客户最终需要的产品,实现抽象产品的接口,定制自己实现的逻辑
抽象工厂通用源码类图
源码实现:
抽象工厂和抽象产品
// 抽象工厂
protocol AbstractCreator {
// 创建产品A
func createPdoructA() -> AbstractProductA
// 创建产品B
func createProductB() -> AbstractProductB
}
// 抽象产品类 A
class AbstractProductA {
func doSomething() {}
}
// 抽象产品类 B
class AbstractProductB {
func doSomething() {}
}
具体工厂
// 具体工厂
class Creator1: AbstractCreator {
func createPdoructA() -> AbstractProductA {
return ProductA1()
}
func createProductB() -> AbstractProductB {
return ProductB1()
}
}
class Creator2: AbstractCreator {
func createPdoructA() -> AbstractProductA {
return ProductA2()
}
func createProductB() -> AbstractProductB {
return ProductB2()
}
}
具体产品
// 具体产品A1
class ProductA1: AbstractProductA {
override func doSomething() {
print("create prodouct A1")
}
}
// 具体产品 A2
class ProductA2: AbstractProductA {
override func doSomething() {
print("create prodouct A2")
}
}
// 具体产品 B1
class ProductB1: AbstractProductB {
override func doSomething() {
print("create prodouct B1")
}
}
// 具体产品 B2
class ProductB2: AbstractProductB {
override func doSomething() {
print("create prodouct B2")
}
}
使用
// 定义两个工厂
let creator1 = Creator1()
let creator2 = Creator2()
// 产生A1对象
let productA1 = creator1.createPdoructA()
// 产生A2对象
let productA2 = creator2.createPdoructA()
// 产生B1对象
let productB1 = creator1.createProductB()
// 产生B2对象
let productB2 = creator2.createProductB()
// do task
productA1.doSomething()
productA2.doSomething()
productB1.doSomething()
productB2.doSomething()
抽象工厂模式的使用流程
1、创建抽象工厂类,提供对应抽象产品的创建方法
2、定义抽象产品类,指定所需的接口,由具体产品类实现接口
3、 实现具体工厂,并在具体工厂中创建具体产品
使用场景
1、类可以让其子类决定在运行期具体实例化的对象
2、封装一组相互关联的类的创建
3、从产品角度讲,如果系统有多于一个的产品族,而系统只消费其中的某一产品;一个系统不应该依赖于产品实例如何被创建、组合和表达的细节,这对于所有形态的工厂模式都是重要的
抽象工厂模式的优点
1、封装性,每个产品的实现类不是高层模块需要关心的,它只需要关注接口即可,它并不需要知道对象是如何创建出来的,只要知道工厂类是谁,我们就能创造出自己需要的对象。
2、切换产品变得容易
抽象工厂模式的缺点
抽象工厂模式的最大缺点就是产品族扩展非常困难。回顾前面的通用代码部分,如果要增加一个产品C,也就是说产品家族由原来的2个增加到3个,抽象类AbstractCreator要增加一个方法createProductC(),然后两个实现类也都需要修改,很显然需要改动的地方非常多,而且这严重违法了开闭原则。
抽象工厂模式和工厂方法模式
目的:都是创建对象而不让客户端知道返回了什么具体对象
工厂模式 | 抽象工厂模式 |
创建一种产品 | 创建一组相互依赖的产品 |
通过对象继承创建抽象产品 | 通过对象组合创建抽象产品 |
子类化创建并重载工厂方法以创建新产品 | 必须修改父类接口才能支持新的产品 |
Cocoa中的抽象工厂模式 - 类族
类簇是基础框架中一种常见的设计模式,是基于抽象工厂的思想,它将若干相关工厂子类集合到一个公有的抽象超类下面。
创建NSNumber实例的方式完全符合抽象工厂模式,如下:
let boolNumber = NSNumber(value: true)
let doubleNumber = NSNumber(value: 2.8)
let intNumber = NSNumber(value: 1)
print("\(object_getClass(boolNumber))")
print("\(object_getClass(doubleNumber))")
print("\(object_getClass(intNumber))")
每个返回对象其实对应着不同的私有子类:
Optional(__NSCFBoolean)
Optional(__NSCFNumber)
Optional(__NSCFNumber)
除了boolNumber是NSCFBoolean,大多数类型都是NSCFNumber,很明显尽管NSNumber对象的类方法返回的是NSNumber实例,但是实际是具体子类的实例,这不就是抽象工厂模式的使用嘛。除了NSNumber,其实NSString、NSArray、NSDictionary都是类簇。
参考