Funções Factory
Parte da seção Object Oriented Programming do Journey de Lua da Coddy — lição 62 de 70.
Ao longo deste curso, você criou objetos chamando construtores diretamente — Circle:new(), Rectangle:new() e assim por diante. Mas e se você quiser criar diferentes tipos de objetos com base em alguma condição, sem que o código de chamada precise saber qual classe específica usar?
É aqui que o padrão Factory entra em cena. Uma factory é simplesmente uma função que cria e retorna objetos. O principal benefício é que quem chama não precisa conhecer os detalhes da criação do objeto — ele apenas solicita à factory o que precisa.
local function createShape(shapeType)
if shapeType == "circle" then
return Circle:new(10)
elseif shapeType == "square" then
return Square:new(5)
end
end
-- O chamador não precisa saber sobre as classes Circle ou Square
local myShape = createShape("circle")
print(myShape:area())
A função factory recebe um argumento de string e decide qual classe instanciar. Isso centraliza a lógica de criação de objetos em um só lugar. Se você adicionar posteriormente um novo tipo de forma, você modifica apenas a factory — não cada parte do código que cria formas.
Factories são especialmente úteis quando a criação de objetos envolve uma configuração complexa, quando você deseja ocultar detalhes de implementação ou quando o tipo exato de objeto depende de condições de tempo de execução, como entrada do usuário ou arquivos de configuração.
Desafio
FácilVamos construir uma Pet Factory! Em vez de criar animais de estimação diretamente chamando o construtor de cada classe, você criará uma função de fábrica que produz o tipo certo de animal com base em um simples argumento de string.
Você organizará seu código em quatro arquivos:
Dog.lua: Crie uma classe Dog com um construtor:new(name)que armazena o nome do animal. Adicione um método:speak()que retorna a string"{name} says: Woof!"(onde {name} é o nome do cachorro).Cat.lua: Crie uma classe Cat com a mesma estrutura — um construtor:new(name)e um método:speak()que retorna"{name} says: Meow!".PetFactory.lua: É aqui que o padrão Factory brilha! Crie uma funçãocreatePet(petType, name)que recebe dois argumentos: uma string indicando o tipo do animal ("dog"ou"cat") e o nome do animal. A função deve retornar o objeto de animal apropriado. Se o tipo for"dog", retorne um novo Dog; se for"cat", retorne um novo Cat.main.lua: Importe seu módulo PetFactory. Leia duas entradas: o tipo do animal e o nome do animal. Use sua função de fábrica para criar o animal, então chame seu método:speak()e imprima o resultado.
A beleza do padrão Factory é que seu código principal não precisa importar Dog ou Cat diretamente — ele conhece apenas a fábrica. A fábrica cuida de todos os detalhes de qual classe instanciar.
Você receberá duas entradas:
- Tipo do animal (seja
"dog"ou"cat") - Nome do animal (uma string)
Por exemplo, se as entradas forem dog e Buddy, a saída deve ser:
Buddy says: Woof!Se as entradas forem cat e Whiskers, a saída deve ser:
Whiskers says: Meow!Folha de consulta
O padrão Factory (ou Fábrica) é um padrão de projeto onde uma função cria e retorna objetos com base em parâmetros fornecidos. O chamador não precisa saber qual classe específica está sendo instanciada — a fábrica cuida dessa decisão.
Uma função fábrica centraliza a lógica de criação de objetos:
local function createShape(shapeType)
if shapeType == "circle" then
return Circle:new(10)
elseif shapeType == "square" then
return Square:new(5)
end
end
local myShape = createShape("circle")
print(myShape:area())
Benefícios do padrão Factory:
- Esconde detalhes de implementação do chamador
- Centraliza a criação de objetos em um só lugar
- Torna fácil adicionar novos tipos — apenas a fábrica precisa de modificação
- Útil quando o tipo de objeto depende de condições de tempo de execução (entrada do usuário, configuração, etc.)
- Útil quando a criação do objeto envolve uma configuração complexa
Experimente você mesmo
-- main.lua
-- Use o PetFactory para criar pets
local PetFactory = require('PetFactory')
-- Ler entradas
local petType = io.read()
local petName = io.read()
-- TODO: Use PetFactory.createPet para criar o pet
-- TODO: Chame o método :speak() do pet e imprima o resultado
Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.
Todas as lições de Object Oriented Programming
1O Conceito 'Self'
Tabelas com Funções'self' ExplícitoA Sintaxe de Dois-pontosPonto vs Dois-pontosRecapitulação - Movendo o Ponto4Projeto: Banco Digital
Configuração do ProjetoMétodo de Depósito7Polimorfismo e Sobrescrita
Sobrescrita de MétodosChamando Métodos da Classe PaiDuck TypingInterface ComumVerificando o TipoRecapitulação - Papéis de Funcionários10Projeto: Gerenciador de Formas
Configuração do ProjetoClasse Retângulo2Padrão de Protótipo de Classe
O Conceito de ProtótipoVinculando com __indexO Construtor :new()Inicializando AtributosInstâncias IndependentesRecapitulação - Fábrica de Carros5Sobrecarga de Operadores em POO
Somando ObjetosSubtraindo ObjetosConcatenando ObjetosComparando Objetos (<, >)Recapitulação - Matemática de Carteira8Encapsulamento
Convenções de NomenclaturaClosures para PrivacidadeAcesso via ClosuresTabelas Somente LeituraLógica de ValidaçãoRecapitulação - Cofre Seguro11Padrões de Projeto (Lite)
Funções FactoryTabela SingletonPadrão IteratorObserver (Listener)Recapitulação - Logger Factory3Estado e Comportamento do Objeto
Variáveis de InstânciaMétodos GetterMétodos SetterPropriedades CalculadasFormatação de StringsVerificações de IgualdadeRecapitulação - Nota do Aluno6Fundamentos de Herança
Configurando a HerançaHerdando MétodosEstendendo o ConstrutorAdicionando Métodos FilhosCompartilhado vs ÚnicoRecapitulação - Hierarquia de Formas