Padrão Factory
Parte da seção Programação Orientada a Objetos do Journey de GO da Coddy. Lição 87 de 107.
O padrão Factory delega a criação de objetos a uma função ou método separado, permitindo que você crie instâncias sem expor a lógica de criação. Diferentemente do Singleton, que controla a quantidade de instâncias, o Factory concentra-se na criação flexível de objetos com base em parâmetros de entrada.
Em Go, uma fábrica normalmente é uma função que retorna um tipo de interface, permitindo criar diferentes tipos concretos por meio de uma API unificada:
type Notifier interface {
Send(message string) string
}
type EmailNotifier struct{}
type SMSNotifier struct{}
func (e EmailNotifier) Send(message string) string {
return "Email: " + message
}
func (s SMSNotifier) Send(message string) string {
return "SMS: " + message
}
func NewNotifier(notifierType string) Notifier {
switch notifierType {
case "email":
return EmailNotifier{}
case "sms":
return SMSNotifier{}
default:
return EmailNotifier{}
}
}A função de fábrica NewNotifier encapsula a decisão sobre qual tipo concreto criar. O código cliente trabalha apenas com a interface Notifier, permanecendo alheio à implementação específica:
notifier := NewNotifier("sms")
result := notifier.Send("Hello!") // "SMS: Hello!"Este padrão se destaca quando você precisa criar objetos com base em condições de execução, quer centralizar uma lógica complexa de inicialização ou precisa adicionar novos tipos facilmente sem modificar o código do cliente. Basta adicionar uma nova struct que implemente a interface e atualizar a função de fábrica.
Desafio
FácilVamos criar um sistema de conversão de documentos usando o padrão Factory! Você criará uma fábrica que produz diferentes conversores de documentos com base no formato de destino, permitindo que o código cliente trabalhe com qualquer conversor por meio de uma interface unificada.
Você organizará seu código em dois arquivos:
converter.go: Defina sua interface de conversor e as implementações concretas.Crie uma interface
Convertercom um métodoConvert(content string) stringque recebe o conteúdo do documento e retorna a saída convertida.Implemente três tipos de conversor:
PDFConverter: seu métodoConvertretornaPDF: [content]HTMLConverter: seu métodoConvertretornaHTML: <p>[content]</p>MarkdownConverter: seu métodoConvertretornaMD: # [content]
Crie uma função de fábrica
NewConverter(format string) Converterque retorna o conversor apropriado com base na string de formato (pdf,htmloumarkdown). Para qualquer formato não reconhecido, retorne umPDFConvertercomo padrão.main.go: Use sua fábrica para criar conversores e processar documentos.Leia um tipo de formato e o conteúdo do documento. Use a fábrica para criar o conversor apropriado, depois converta o conteúdo e imprima o resultado.
As seguintes entradas serão fornecidas:
- Linha 1: Tipo de formato (
pdf,html,markdownou qualquer outra coisa) - Linha 2: Conteúdo do documento a ser convertido
Por exemplo, dada a entrada:
html
Welcome to Go ProgrammingSua saída deve ser:
HTML: <p>Welcome to Go Programming</p>E dada a entrada:
markdown
Chapter OneSua saída deve ser:
MD: # Chapter OneE dada a entrada:
pdf
Annual Report 2024Sua saída deve ser:
PDF: Annual Report 2024E dada a entrada:
docx
Meeting NotesSua saída deve ser:
PDF: Meeting NotesObserve como o código principal não precisa conhecer os tipos específicos de conversor. Ele apenas solicita um conversor à fábrica e usa a interface. Isso facilita a adição de novos formatos posteriormente, sem alterar o código cliente!
Experimente você mesmo
package main
import (
"bufio"
"fmt"
"os"
)
func main() {
scanner := bufio.NewScanner(os.Stdin)
// Ler o tipo de formato
scanner.Scan()
format := scanner.Text()
// Ler o conteúdo do documento
scanner.Scan()
content := scanner.Text()
// TODO: Use a factory para criar o conversor apropriado
// TODO: Converta o conteúdo e imprima o resultado
fmt.Println(result)
}
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
1Fundamentos de OOP em Go
Arquivos ExternosWorkspace e Módulos do GoPacotes e ImportsNomes Exportados vs. Não ExportadosIntrodução à OOP em GoStructs como ClassesDefinindo Métodos em StructsReceptores de Ponteiro vs. de ValorInicialização de StructsFunções ConstrutorasRecapitulação — Calculadora Simples4Interfaces
Introdução às InterfacesImplementação ImplícitaInterface como ContratoInterface Vazia (any)Asserção de TipoSwitch de TipoComposição de InterfacesInterfaces Stringer e ErrorRecapitulação - Calculadora de Formas7Encapsulamento
Campos Exportados vs. Não ExportadosEncapsulamento no Nível de PacoteMétodos Getters e SettersOcultação de Informações em GoRecapitulação - Registros de Alunos10Genéricos (Go 1.18+)
Introdução aos genéricosParâmetros de tipoRestrições de tipoStructs genéricasAlternativa para métodos genéricosRecapitulação - Coleção genérica13Padrões de Projeto — Parte 1
Introdução aos Padrões de ProjetoPadrão SingletonPadrão FactoryPadrão Abstract FactoryPadrão ObserverPadrão Strategy2Tipos e Structs em Profundidade
Tipos Básicos e CompostosDefinições de Tipos PersonalizadosTags de StructStructs AnônimasStructs AninhadasValores Zero e PadrõesRecapitulação - Livro de Contatos5Composição em vez de herança
Por que Go não tem herançaNoções básicas de incorporação de structsPromoção de métodosIncorporação de várias structsIncorporação vs agregaçãoOcultação de métodos incorporadosRecapitulação - Hierarquia de funcionários8Tratamento de Erros e OOP
A interface errorTipos de Erro PersonalizadosEncapsulamento de Erros (fmt.Errorf)Erros Sentinelaerrors.Is() e errors.As()Panic, Defer e RecoverRecapitulação - Analisador de Arquivos3Ponteiros e Memória
Fundamentos de Ponteiros em GoPonteiros para StructsPassagem por Valor vs. ReferênciaA Função new()Coleta de Lixo em GoRecapitulação - Construtor de Lista Ligada6Polimorfismo em Go
Polimorfismo via InterfacesDuck Typing em GoRegras de Satisfação de InterfacesColeções PolimórficasInjeção de DependênciasRecapitulação - Processador de Pagamentos9Concorrência e OOP
Fundamentos de GoroutinesCanais e comunicaçãoCanais com e sem bufferInstrução selectsync.Mutex e sync.RWMutexsync.WaitGroupDesign de structs thread-safeRevisão - Worker PoolPratique por conta própria: Compilador de Go online