毫无疑问,工厂这个词在讨论编程时是程序员最常用的词之一。与此同时,它们究竟意味着什么不同。它可能是生成对象类(多态或非多态),返回对象方法(静态或非静态),甚至是常规构造函数。
但是,并非生成对象的所有内容都可以称为工厂。此外,这个词可以描述四人帮的工厂中的两种不同的创作设计模式 - 工厂方法和抽象工厂。
我想深入了解它们的细节,特别注意它们的经典实现和理解。
抽象工厂

- 封装由通用接口绑定的具体类型。在这种情况下,可以理解为一种类型,即工厂。 Factory的公共API由方法集(静态或非静态)组成,它返回公共接口类型的实例并具有有意义的名称,因此我们知道必须为特定目的调用哪一个。
- 第二个类似于第一个,一般而言,我们使用的所有场景或多或少都相似。这是因为在程序的不同部分中创建一种类型或一组类型的实例。同样,工厂封装了创建代码,但它的动机不同。如果该代码很复杂并且不受初始化程序调用的限制,则这是特别相关的。
在iOS开发中,运行UIViewController子类非常方便。实际上,它是iOS软件开发中流行的类型之一,在使用之前几乎总是被子类化。具体类对于客户端代码通常并不重要。
我将尽力使代码示例尽可能接近Gang of Four的书中的经典模式实现,尽管现实世界代码可以通过某种方式进行简化。只有深入了解基础中的原理才能让人更自由地使用它。
详细代码
假设我们的应用程序销售车辆,视图/展示取决于其类型。我们将为不同的车辆类型使用不同的UIViewController子类。除此之外,所有车辆的状态都不同 - 新的和二手的。
import UIKit
enum VehicleCondition {
case new
case used
}
final class BicycleViewController: UIViewController {
private let condition: VehicleCondition
init(condition: VehicleCondition) {
self.condition = condition
super.init(nibName: nil, bundle: nil)
}
required init?(coder aDecoder: NSCoder) {
fatalError("BicycleViewController: init(coder:) has not been implemented.")
}
}
final class ScooterViewController: UIViewController {
private let condition: VehicleCondition
init(condition: VehicleCondition) {
self.condition = condition
super.init(nibName: nil, bundle: nil)
}
required init?(coder aDecoder: NSCoder) {
fatalError("ScooterViewController: init(coder:) has not been implemented.")
}
}
因此,我们有一组相同组的类型,其实例根据条件在类似的地方创建。例如,用户点击列表中的项目 - 根据点击的车辆的类型,它的创建方式不同。视图控制器的初始值设定项具有必须每次传递的参数值。这些论点是否揭示了创建工厂的优势,唯一知道只是所需控制器创建细节的类型?
显然,这个例子很简单。在现实世界中,介绍这个工厂将是过度工程。然而,可以想象在初始化器中具有多个参数的更多车辆类型,并且抽象工厂优势变得更加明显。
protocol VehicleViewControllerFactory {
func makeBicycleViewController() -> UIViewController
func makeScooterViewController() -> UIViewController
}
介wift API编程指南建议工厂方法以“make”为前缀命名。
Gang of Four的例子是用C ++编写的,基于继承和虚函数。在Swift中,我们更接近面向协议的编程技术。
工厂接口仅包含两种方法,为自行车和踏板摩托车车创建视图控制器。这些方法返回公共父类的实例。因此,意识的区域扩散受到真正需要的区域的限制。
让我们添加两个实现抽象工厂接口的具体工厂:
struct NewVehicleViewControllerFactory: VehicleViewControllerFactory {
func makeBicycleViewController() -> UIViewController {
return BicycleViewController(condition: .new)
}
func makeScooterViewController() -> UIViewController {
return ScooterViewController(condition: .new)
}
}
struct UsedVehicleViewControllerFactory: VehicleViewControllerFactory {
func makeBicycleViewController() -> UIViewController {
return BicycleViewController(condition: .used)
}
func makeScooterViewController() -> UIViewController {
return ScooterViewController(condition: .used)
}
}
因此,在我们的案例中,具体工厂负责不同条件下的新车和二手车。
从此以后,必要的视图控制器就像这样创建:
let factory: VehicleViewControllerFactory = NewVehicleViewControllerFactory()
let vc = factory.makeBicycleViewController()
用工厂封装类

第一个是关于具体类型的封装。记住用于在车辆上显示数据的相同视图控制器子类:
final class BicycleViewController: UIViewController { }
final class ScooterViewController: UIViewController { }
假设我们正在处理一个单独的模块,例如库。在这种情况下,上面的视图控制器类保持内部(默认情况下),并且工厂充当公共API。 Factory的方法返回众所周知的视图控制器的父类实例。因此,关于具体类型的知识受到以下模块的限制:
public struct VehicleViewControllerFactory {
func makeBicycleViewController() -> UIViewController {
return BicycleViewController()
}
func makeScooterViewController() -> UIViewController {
return ScooterViewController()
}
}
将创建转移到工厂

假设我们也出售汽车。毫无疑问,它是一种更复杂的车辆,具有更多参数和选项。让我们用相应的燃油类型,传动类型和车轮直径参数实现相应的视图控制器:
enum Condition {
case new
case used
}
enum EngineType {
case diesel
case gas
}
struct Engine {
let type: EngineType
}
enum TransmissionType {
case automatic
case manual
}
final class CarViewController: UIViewController {
private let condition: Condition
private let engine: Engine
private let transmission: TransmissionType
private let wheelDiameter: Int
init(engine: Engine,
transmission: TransmissionType,
wheelDiameter: Int = 16,
condition: Condition = .new) {
self.engine = engine
self.transmission = transmission
self.wheelDiameter = wheelDiameter
self.condition = condition
super.init(nibName: nil, bundle: nil)
}
required init?(coder aDecoder: NSCoder) {
fatalError("CarViewController: init(coder:) has not been implemented.")
}
}
视图控制器初始化
let engineType = EngineType.diesel
let engine = Engine(type: engineType)
let transmission = TransmissionType.automatic
let wheelDiameter = 18
let vc = CarViewController(engine: engine,
transmission: transmission,
wheelDiameter: wheelDiameter)
或者我们可以实现一个专门的工厂来处理初始化:
struct UsedCarViewControllerFactory {
let engineType: EngineType
let transmissionType: TransmissionType
let wheelDiameter: Int
func makeCarViewController() -> UIViewController {
let engine = Engine(type: engineType)
return CarViewController(engine: engine,
transmission: transmissionType,
wheelDiameter: wheelDiameter,
condition: .used)
}
像这样使用它:
let factory = UsedCarViewControllerFactory(engineType: .gas, transmissionType: .manual, wheelDiameter: 17)
let vc = factory.makeCarViewController()
工厂方法

Gang of Four的书中说这种模式也被称为虚拟构造函数,并且有充分的理由。在C ++中,如果被派生类覆盖,我们将函数称为虚拟函数。但是,人们不能将构造函数声明为虚拟,并且可能,模式发明是由模拟所需行为的尝试引起的。
多态创建

作为模式使用的典型示例,让我们考虑一种情况,即当在方法内部创建的对象实现时,同一层次结构中的不同类型具有类似的方法实现。让我们尝试通过将对象创建移到外部并通过将其在层次结构中向上移动一步来使类似方法变得通用来改善这种情况。
让我们回到我们的车辆视图控制器:
final class BicycleViewController: UIViewController { }
final class ScooterViewController: UIViewController { }
现在,让我们考虑一下这个视图控制器的展示并声明一个协调器:
protocol Coordinator {
var presentingViewController: UIViewController? { get set }
func start()
}
考虑这些协调器实现:
final class BicycleCoordinator: Coordinator {
weak var presentingViewController: UIViewController?
func start() {
let vc = BicycleViewController()
presentingViewController?.present(vc, animated: true)
}
}
final class ScooterCoordinator: Coordinator {
weak var presentingViewController: UIViewController?
func start() {
let vc = ScooterViewController()
presentingViewController?.present(vc, animated: true)
}
}
方法start()具有类似的实现,除了在内部创建的视图控制器。让我们把创建移到外面:
protocol Coordinator {
var presentingViewController: UIViewController? { get set }
func start()
func makeViewController() -> UIViewController
}
并使用start()方法的默认实现扩展协议:
extension Coordinator {
func start() {
let vc = makeViewController()
presentingViewController?.present(vc, animated: true)
}
}
实现代码是:
final class BicycleCoordinator: Coordinator {
weak var presentingViewController: UIViewController?
func makeViewController() -> UIViewController {
return BicycleViewController()
}
}
final class ScooterCoordinator: Coordinator {
weak var presentingViewController: UIViewController?
func makeViewController() -> UIViewController {
return ScooterViewController()
}
}