Padrão Singleton
Parte da seção Programação Orientada a Objetos do Journey de Swift da Coddy. Lição 42 de 57.
Um padrão de projeto é uma solução comprovada para um problema comum de projeto. O padrão singleton garante que uma classe tenha exatamente uma instância, acessível de qualquer lugar. Em Swift, ele é um static let que contém a instância, além de um private init para que ninguém possa criar outra:
final class Settings {
static let shared = Settings()
var theme = "light"
private init() {}
}
Settings.shared.theme = "dark"
print(Settings.shared.theme)Saída:
darkCada uso de Settings.shared refere-se ao mesmo objeto, portanto uma alteração feita em uma parte do programa fica visível em todos os lugares. static let é criado sob demanda no primeiro uso e com segurança mesmo quando várias threads são iniciadas ao mesmo tempo:
final class Counter {
static let shared = Counter()
private(set) var hits = 0
private init() {}
func hit() { hits += 1 }
}
func pageA() { Counter.shared.hit() }
func pageB() { Counter.shared.hit(); Counter.shared.hit() }
pageA()
pageB()
print(Counter.shared.hits)
print(Counter.shared === Counter.shared)Saída:
3
trueComo o inicializador é privado, Settings() não compila fora da classe, o que mantém a promessa de "apenas uma":
// let other = Settings() // erro: o inicializador de 'Settings' é inacessível devido ao nível de proteção 'private'Use singletons com moderação. Um singleton é um estado global: qualquer código pode alterá-lo, e os testes não podem começar facilmente a partir de uma cópia limpa. Eles são adequados para coisas que realmente existem uma por programa, como um logger ou a configuração do app; passar um objeto como parâmetro costuma ser mais claro.
// mais claro para testar: o logger é passado
func process(order: Order, log: Logger) { log.write("processing \(order.id)") }Desafio
FácilComplete o singleton Logger. Ele tem uma instância static let shared, um inicializador privado, um array private(set) de entries e log(_:level:), que armazena [INFO] message ou [ERROR] message (o nível é info ou error). errorCount é uma propriedade computada. O código fornecido chama Logger.shared a partir de duas funções diferentes, portanto ambas devem acessar a mesma instância.
O código fornecido lê linhas info,message ou error,message, envia as linhas de informação por meio de handleInfo e as linhas de erro por meio de handleError e, em seguida, imprime cada entrada e errors: 1.
Seu código deve ficar em Logger.swift e Functions.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: ",", maxSplits: 1).map(String.init)
if p[0] == "error" { handleError(p[1]) } else { handleInfo(p[1]) }
}
for e in Logger.shared.entries { print(e) }
print("errors: \(Logger.shared.errorCount)")
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