持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第2天,点击查看活动详情
- 本文主要介绍iOS设计模式中的
工厂方法,工厂方法基本上面向对象语言都能看到工厂方法,工厂方法模式是抽象工厂模式的组成部分。各种具体工厂重载其抽象工厂父类中定义的工厂方法,并用这个工厂的方法创建自己的产品。
1.什么是工厂方法模式
工厂方法模式是一种创建型设计模式, 其在父类中提供一个创建对象的方法, 允许子类决定实例化对象的类型。
工厂方法也成虚构造器,它使用于这种情况:一个类无法预期生成那个类的对象,想让其子类来指定所生产的对象。
我们也可以类比真实的工厂场景,比如汽车厂生产汽车,可以生产SUV,轿车,电动车等。你让工厂给你生产些产品,你给它们发送一个‘生产产品’的消息,根据我们的要求,生产对应的汽车,我们把“生产”这个有魔力的词称作工厂方法。
生产者自身不用是抽象工厂,可以是任何类。要点在于不是直接创建对象,而是使用类或者对象的工厂方法创建具体产品,并以抽象类型返回。
2. 何时使用工厂方法
以下的情形,可以使用工厂方法模式:
编译时无法准确的预期要创建对象的类,有多种类型- 类想让其
子类决定在运行时创建什么 - 类有若干辅助类为
其子类,而你想要将返回哪个类这一信息局部化。 工厂方法能给予类在变更返回哪一种对象这一点上有更多的灵活性,比如在Cocoa Touch框架的NSNumber,通常我们可以使用alloc init创建,这没什么用,使用预先定义的类工厂方法来创建才有意义。比如使用numberWithBool进行实例化,得到的子类是NSCFBoolean类型的子类
当然我们可以使用其他的工厂构造方法生成不同的子类
3. 为何这是创建对象的安全方法
与直接创建新的具对象相比,使用工厂方法创建对象可以算是一种最佳的方式。工厂方法模式让客户程序可以要求工厂方法创建的对象拥有一组共同的行为,所以往类层次结构中引入新的具体产品并不需要修改原有的客户端代码,应为返回具的任何具体对象的接口都跟客户端一直在用的从前接口相同。
4. 代码表示
使用代码来表示
import XCTest
/// The Creator protocol declares the factory method that's supposed to return a
/// new object of a Product class. The Creator's subclasses usually provide the
/// implementation of this method.
protocol Creator {
/// Note that the Creator may also provide some default implementation of
/// the factory method.
func factoryMethod() -> Product
/// Also note that, despite its name, the Creator's primary responsibility
/// is not creating products. Usually, it contains some core business logic
/// that relies on Product objects, returned by the factory method.
/// Subclasses can indirectly change that business logic by overriding the
/// factory method and returning a different type of product from it.
func someOperation() -> String
}
/// This extension implements the default behavior of the Creator. This behavior
/// can be overridden in subclasses.
extension Creator {
func someOperation() -> String {
// Call the factory method to create a Product object.
let product = factoryMethod()
// Now, use the product.
return "Creator: The same creator's code has just worked with " + product.operation()
}
}
/// Concrete Creators override the factory method in order to change the
/// resulting product's type.
class ConcreteCreator1: Creator {
/// Note that the signature of the method still uses the abstract product
/// type, even though the concrete product is actually returned from the
/// method. This way the Creator can stay independent of concrete product
/// classes.
public func factoryMethod() -> Product {
return ConcreteProduct1()
}
}
class ConcreteCreator2: Creator {
public func factoryMethod() -> Product {
return ConcreteProduct2()
}
}
/// The Product protocol declares the operations that all concrete products must
/// implement.
protocol Product {
func operation() -> String
}
/// Concrete Products provide various implementations of the Product protocol.
class ConcreteProduct1: Product {
func operation() -> String {
return "{Result of the ConcreteProduct1}"
}
}
class ConcreteProduct2: Product {
func operation() -> String {
return "{Result of the ConcreteProduct2}"
}
}
/// The client code works with an instance of a concrete creator, albeit through
/// its base protocol. As long as the client keeps working with the creator via
/// the base protocol, you can pass it any creator's subclass.
class Client {
// ...
static func someClientCode(creator: Creator) {
print("Client: I'm not aware of the creator's class, but it still works.\n"
+ creator.someOperation())
}
// ...
}
/// Let's see how it all works together.
class FactoryMethodConceptual: XCTestCase {
func testFactoryMethodConceptual() {
/// The Application picks a creator's type depending on the
/// configuration or environment.
print("App: Launched with the ConcreteCreator1.")
Client.someClientCode(creator: ConcreteCreator1())
print("\nApp: Launched with the ConcreteCreator2.")
Client.someClientCode(creator: ConcreteCreator2())
}
}
输出结果
App: Launched with the ConcreteCreator1.
Client: I'm not aware of the creator's class, but it still works.
Creator: The same creator's code has just worked with {Result of the ConcreteProduct1}
App: Launched with the ConcreteCreator2.
Client: I'm not aware of the creator's class, but it still works.
Creator: The same creator's code has just worked with {Result of the ConcreteProduct2}
5. 总结
工厂方法是面向对象软件设计中应用非常普遍的设计模式,工厂方法从代码中消除了对应用程序特有类的耦合,代码只需要处理product抽象接口,所以同一代码得以复用。