Patrón Factory
Parte de la sección Programación orientada a objetos del Journey de Swift de Coddy. Lección 43 de 57.
El patrón fábrica coloca la creación de objetos en un solo lugar. Los llamadores solicitan lo que necesitan, a menudo por nombre o tipo, y reciben un objeto listo, sin saber qué tipo concreto se creó:
protocol Shape { func area() -> Double }
struct Square: Shape { let side: Double; func area() -> Double { side * side } }
struct Circle: Shape { let r: Double; func area() -> Double { 3 * r * r } }
enum ShapeFactory {
static func make(_ kind: String, size: Double) -> (any Shape)? {
switch kind {
case "square": return Square(side: size)
case "circle": return Circle(r: size)
default: return nil
}
}
}
print(ShapeFactory.make("square", size: 3)!.area())
print(ShapeFactory.make("hexagon", size: 3) == nil)Salida:
9.0
trueLa persona que llama depende únicamente del protocolo. Añadir una nueva forma significa cambiar la fábrica, no todos los lugares que crean formas:
protocol Notifier { func send(_ m: String) -> String }
struct Email: Notifier { func send(_ m: String) -> String { "email: \(m)" } }
struct SMS: Notifier { func send(_ m: String) -> String { "sms: \(m)" } }
func makeNotifier(for user: String) -> any Notifier {
user.hasSuffix("@mail.com") ? Email() : SMS()
}
print(makeNotifier(for: "ada@mail.com").send("hi"))
print(makeNotifier(for: "555-0100").send("hi"))Salida:
email: hi
sms: hiLos métodos de fábrica estáticos en el propio tipo son una forma más sencilla del patrón. Dan nombre a formas comunes de construir un valor:
struct Color {
let r: Int, g: Int, b: Int
static func gray(_ v: Int) -> Color { Color(r: v, g: v, b: v) }
static let white = Color(r: 255, g: 255, b: 255)
}
print(Color.gray(100).g)
print(Color.white.b)Salida:
100
255Un enum sin casos, como ShapeFactory, es una forma común de agrupar funciones de fábrica: no se puede instanciar, por lo que funciona exclusivamente como un espacio de nombres.
enum ShapeFactory { // sin casos: no se puede crear
static func make(_ kind: String, size: Double) -> (any Shape)? { ... }
}Desafío
FácilEscribe una fábrica para planes de precios. El protocolo Plan tiene name y price(forUsers:) -> Int. Implementa Free (0, y solo hasta 3 usuarios: por encima de esa cantidad, el precio es -1, lo que significa que no está permitido), Team (10 por usuario) y Enterprise (500 fijos más 5 por cada usuario por encima de 100). Completa PlanFactory.make(_:), que devuelve el plan para free, team o enterprise, y nil en cualquier otro caso.
El código proporcionado lee líneas con el formato plan,users e imprime team for 12 users: 120, free does not allow 5 users o unknown plan: gold.
Tu código debe ir en Plan.swift, Free.swift, Team.swift, Enterprise.swift y PlanFactory.swift. main.swift contiene el código proporcionado de entrada/salida y no se puede editar.
Pruébalo tú mismo
// Código de entrada/salida suministrado: mantenlo tal como está
var input: [String] = []
while let line = readLine() { input.append(line) }
for line in input {
let p = line.split(separator: ",").map(String.init)
let users = Int(p[1])!
guard let plan = PlanFactory.make(p[0]) else {
print("unknown plan: \(p[0])")
continue
}
let price = plan.price(forUsers: users)
print(price < 0 ? "\(plan.name) does not allow \(users) users" : "\(plan.name) for \(users) users: \(price)")
}
Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.
Todas las lecciones de Programación orientada a objetos
1Clases y objetos
Trabajar con archivosDefinir clasesMétodos y selfInicializadoresLas clases son referenciasRepaso: tarjeta de biblioteca4Encapsulación
Control de accesoSolo lectura desde fueraProtección del estadoInicializadores que pueden fallarRepaso - Cuenta bancaria7Polimorfismo y genéricos
PolimorfismoConversión de tiposFunciones genéricasTipos genéricosRepaso - Calculadora de formas2Structs y tipos por valor
StructsSemántica de valoresMétodos mutablesStruct o claseRepaso - elemento del inventario5Herencia
SubclasesSobrescritura de métodosInicializadores y superfinal y jerarquíasRepaso: jerarquía de empleados8Protocolos estándar
CustomStringConvertibleEquatableComparableHashableRepaso - Ordenamiento personalizado11Proyecto: Gestión de bibliotecas
Libros y miembrosPréstamo de librosPractica por tu cuenta: Playground de Swift