工厂方法是一种创建型设计模式,其在父类中提供一个创建对象的接口,允许子类决定实例化对象的类型。
现在我们来定一个抽象产品类:
protocol Animal {
var type:String { get set }
func say()
}
一个动物抽象类,里边有个type属性表示种类,一个say方法会发出声音。
然后我们搞两个具体的动物:
class Dog: Animal {
var type: String = ""
func say() {
print("\(type)汪汪汪")
}
}
class Cat: Animal {
var type: String = ""
func say() {
print("\(type)喵喵喵")
}
}
一猫一狗两个具体动物类,分别实现say方法。
现在我们来创建工厂超类:
protocol AnimalFactory {
func createProduct() -> Animal
}
这个类目前只有一个功能,创建并返回一个动物。
我们来分别实现两个具体工厂:
class DogFactory: AnimalFactory {
func createProduct() -> Animal {
let dog = Dog()
dog.type = "中华田园犬"
return dog
}
}
class CatFactory: AnimalFactory {
func createProduct() -> Animal {
let cat = Cat()
cat.type = "波斯猫"
return cat
}
}
这两个工厂,分别创建猫和狗。客户端调用时可以这样:
DogFactory().createProduct().say()
CatFactory().createProduct().say()
打印结果是:
中华田园犬汪汪汪
波斯猫喵喵喵
这样利用工厂方法看起来跟直接使用猫类和狗类来创建对象好像没什么区别,但是却有质的改变:
1.工厂方法封装了创建对象的过程,简化客户端的创建流程,隔离了创建者和具体对象的紧密联系。
2.工厂方法里还可以实现对象池,管理对象的复用逻辑。
3.符合开闭原则,添加新的产品只需要添加一个产品类和一个工厂类。
4.符合单一职责原则,每个工厂类就负责一个产品。