Padrão Factory
Parte da seção Programação Orientada a Objetos do Journey de Swift da Coddy. Lição 43 de 57.
O padrão factory concentra a criação de objetos em um só lugar. Os chamadores solicitam o que precisam, geralmente por nome ou tipo, e recebem um objeto pronto, sem saber qual tipo concreto foi criado:
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)Saída:
9.0
trueO chamador depende apenas do protocolo. Adicionar uma nova forma significa alterar a fábrica, não todos os lugares que criam 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"))Saída:
email: hi
sms: hiOs métodos de fábrica estáticos no próprio tipo são uma forma mais simples do padrão. Eles dão nomes a maneiras comuns de construir um 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)Saída:
100
255Um enum sem casos, como ShapeFactory, é uma forma comum de agrupar funções de fábrica: ele não pode ser instanciado, portanto funciona exclusivamente como um namespace.
enum ShapeFactory { // sem casos: não pode ser criado
static func make(_ kind: String, size: Double) -> (any Shape)? { ... }
}Desafio
FácilEscreva uma fábrica para planos de preços. O protocolo Plan possui name e price(forUsers:) -> Int. Implemente Free (0, e somente até 3 usuários: acima disso, o preço é -1, significando que não é permitido), Team (10 por usuário) e Enterprise (500 fixos mais 5 por usuário acima de 100). Complete PlanFactory.make(_:), que retorna o plano para free, team ou enterprise, e nil caso contrário.
O código fornecido lê linhas plan,users e imprime team for 12 users: 120, free does not allow 5 users ou unknown plan: gold.
Seu código deve estar em Plan.swift, Free.swift, Team.swift, Enterprise.swift e PlanFactory.swift. main.swift contém o código fornecido de entrada/saída e não pode ser editado.
Experimente você mesmo
// Código de entrada/saída fornecido: mantenha-o 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 lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.
Todas as lições de Programação Orientada a Objetos
1Classes e Objetos
Trabalhando com ArquivosDefinindo ClassesMétodos e selfInicializadoresClasses são ReferênciasRevisão - Cartão da Biblioteca4Encapsulamento
Controle de AcessoSomente Leitura ExternaProtegendo o EstadoInicializadores que Podem FalharRevisão - Conta Bancária7Polimorfismo e Genéricos
PolimorfismoConversão de TiposFunções GenéricasTipos GenéricosRevisão - Calculadora de Formas2Structs e Tipos de Valor
StructsSemântica de ValorMétodos MutáveisStruct ou ClasseRecapitulação - Item de Inventário5Herança
SubclassesSobrescrita de métodosInicializadores e superfinal e hierarquiasRecapitulação - Hierarquia de funcionários8Protocolos Padrão
CustomStringConvertibleEquatableComparableHashableRecapitulação - Ordenação Personalizada11Projeto: Gerenciamento de Biblioteca
Livros e MembrosEmpréstimo de LivrosPratique por conta própria: Playground de Swift