O padrão de design Factory é amplamente utilizado na programação orientada a objetos. Ele oferece uma interface para criar objetos, mas permite que as subclasses decidam quais classes instanciar. Neste artigo, vamos explorar como implementar o padrão Factory em Golang, entender seus benefícios e analisar um exemplo prático de uso inspirado em situações do dia-a-dia.
O que é o Factory?
O Factory define uma interface para criar objetos, mas delega a responsabilidade de instanciar a classe concreta às subclasses. Isso promove a criação de objetos de maneira desacoplada e flexível, permitindo que o código seja mais modular e fácil de manter.
Benefícios
- Desacoplamento: Separa a criação de objetos da sua implementação, promovendo um código mais limpo e modular.
- Flexibilidade: Facilita a introdução de novas classes sem modificar o código existente.
- Manutenção: Torna o código mais fácil de manter e evoluir, pois a lógica de criação está centralizada em um único lugar.
Implementando uma Factory
Vamos utilizar um exemplo do dia-a-dia para ilustrar o padrão Factory: um sistema para pedidos de comida, onde alguns diferentes tipos de refeições (Pizza e Salada) podem ser criados.
1 - Criando a interface
Primeiro, precisamos definir uma interface que será implementada por todas as "classes concretas" de refeições.
package main
type Food interface {
Prepare()
}
2 - Criando um ENUM e implementando a interface
Para facilitar a nossa vida durante o desenvolvimento e evitar de digitar algo errado durante a validação, uma boa prática é criar um ENUM para ter uma consistência e também facilitar caso queiramos adicionar novas comidas no futuro
package main
type FoodType int
const (
PizzaType FoodType = iota
SaladType
)
type Food interface {
Prepare()
}
E agora vamos implementar a interface Food
. No exemplo vamos apenas exibir uma mensagem, na vida real aqui é onde seria criado o objeto que estamos trabalhando
package main
type FoodType int
const (
PizzaType FoodType = iota
SaladType
)
type Food interface {
Prepare()
}
type Pizza struct{}
func (p Pizza) Prepare() {
fmt.Println("Preparing a Pizza...")
}
type Salad struct{}
func (s Salad) Prepare() {
fmt.Println("Preparing a Salad...")
}
3 - Criando a Factory
Agora, vamos criar a factory que decidirá qual classe concreta instanciar com base no enum que recebeu como parâmetro.
package main
type FoodFactory struct{}
func (f FoodFactory) CreateFood(ft FoodType) Food {
switch ft {
case PizzaType:
return &Pizza{}
case SaladType:
return &Salad{}
default:
return nil
}
}
4 - Utilizando a Factory
Finalmente, vamos utilizar a fábrica para criar nossas comidas.
package main
func main() {
kitchen := FoodFactory{}
pizza := kitchen.CreateFood(PizzaType)
if pizza != nil {
pizza.Prepare()
}
salad := kitchen.CreateFood(SaladType)
if salad != nil {
salad.Prepare()
}
}
Esse será o resultado após rodarmos nossa aplicação:
Preparing a Pizza...
Preparing a Salad...
Resumo do que fizemos
- Interface
Food
: Define o contrato que todas as refeições concretas devem seguir, garantindo que todas implementem o método Prepare. - Enum
FoodType
: Utiliza constantes tipadas para representar os diferentes tipos de comida, aumentando a legibilidade e a segurança do código. - Classes concretas (
Pizza
eSalad
): Implementam a interface Food e fornecem suas próprias implementações do método Prepare. -
FoodFactory
: Contém a lógica de criação de objetos. O método CreateFood decide qual classe concreta instanciar com base no enum FoodType. - Método
main
: Demonstra o uso da fábrica para criar diferentes objetos e chamar seus métodos, ilustrando a flexibilidade e o desacoplamento proporcionados pelo padrão Factory.
Conclusão
O padrão de design Factory é uma poderosa ferramenta para promover o desacoplamento e a flexibilidade na criação de objetos. Em Golang, a implementação deste padrão é direta e eficaz, permitindo a criação de sistemas modulares e fáceis de manter. Com o uso de interfaces e fábricas, podemos centralizar a lógica de criação e simplificar a evolução do código à medida que novos requisitos surgem.
Top comments (0)