
Factory Method en Go
Factory method es un patrón de diseño creacional que resuelve el problema de crear objetos de producto sin especificar sus clases concretas.
El patrón Factory Method define un método que debe utilizarse para crear objetos, en lugar de una llamada directa al constructor (operador new
). Las subclases pueden sobrescribir este método para cambiar las clases de los objetos que se crearán.
Si no sabes la diferencia entre varios patrones y conceptos de la fábrica, lee nuestra Comparación de fábricas.
Ejemplo conceptual
Resulta imposible implementar el clásico patrón Factory Method en Go debido a la falta de funciones POO, como las clases y la herencia. Sin embargo, podemos implementar la versión básica del patrón, el Simple Factory.
En este ejemplo, vamos a crear varios tipos de armas utilizando una estructura de fábrica.
Primero, creamos la interfaz iGun
, que define todos los métodos con los que debería contar un arma. Hay un tipo de estructura gun
que implementa la interfaz iGun. Dos armas concretas (ak47
y musket
), ambas integran la estructura del arma e, indirectamente, implementan todos los métodos iGun
.
La estructura gunFactory
sirve como fábrica, que crea armas del tipo deseado en base a un argumento entrante. main.go actúa como cliente. En lugar de interactuar directamente con ak47
o musket
, se basa en gunFactory
para crear instancias de varias armas, utilizando únicamente parámetros de cadenas para controlar la producción.
iGun.go: Interfaz de producto
package main
type IGun interface {
setName(name string)
setPower(power int)
getName() string
getPower() int
}
gun.go: Producto concreto
package main
type Gun struct {
name string
power int
}
func (g *Gun) setName(name string) {
g.name = name
}
func (g *Gun) getName() string {
return g.name
}
func (g *Gun) setPower(power int) {
g.power = power
}
func (g *Gun) getPower() int {
return g.power
}
ak47.go: Producto concreto
package main
type Ak47 struct {
Gun
}
func newAk47() IGun {
return &Ak47{
Gun: Gun{
name: "AK47 gun",
power: 4,
},
}
}
musket.go: Producto concreto
package main
type musket struct {
Gun
}
func newMusket() IGun {
return &musket{
Gun: Gun{
name: "Musket gun",
power: 1,
},
}
}
gunFactory.go: Fábrica
package main
import "fmt"
func getGun(gunType string) (IGun, error) {
if gunType == "ak47" {
return newAk47(), nil
}
if gunType == "musket" {
return newMusket(), nil
}
return nil, fmt.Errorf("Wrong gun type passed")
}
main.go: Código cliente
package main
import "fmt"
func main() {
ak47, _ := getGun("ak47")
musket, _ := getGun("musket")
printDetails(ak47)
printDetails(musket)
}
func printDetails(g IGun) {
fmt.Printf("Gun: %s", g.getName())
fmt.Println()
fmt.Printf("Power: %d", g.getPower())
fmt.Println()
}
output.txt: Resultado de la ejecución
Gun: AK47 gun
Power: 4
Gun: Musket gun
Power: 1