![Prototype](/images/patterns/cards/prototype-mini.png?id=bc3046bb39ff36574c08d49839fd1c8e)
Prototype en Go
Prototype es un patrón de diseño creacional que permite la clonación de objetos, incluso los complejos, sin acoplarse a sus clases específicas.
Todas las clases prototipo deben tener una interfaz común que haga posible copiar objetos incluso si sus clases concretas son desconocidas. Los objetos prototipo pueden producir copias completas, ya que los objetos de la misma clase pueden acceder a los campos privados de los demás.
Ejemplo conceptual
Vamos a intentar imaginar el patrón Prototype utilizando un ejemplo basado en el sistema de archivos del sistema operativo. El sistema de archivos del SO es recursivo: las carpetas contienen archivos y carpetas, que también pueden incluir archivos y carpetas, y así sucesivamente.
Cada archivo y carpeta puede representarse por una interfaz inode
. La interfaz inode
incluye también la función clone
.
Las estructuras file
y folder
implementan las funciones print
y clone
, ya que son del tipo inode
. Observa también la función clone
tanto en file
como en folder
. La función clone
en ambas devuelve una copia del archivo o la carpeta respectivos. Durante la clonación, añadimos la palabra clave “_clone” para el campo del nombre.
inode.go: Interfaz prototipo
package main
type Inode interface {
print(string)
clone() Inode
}
file.go: Prototipo concreto
package main
import "fmt"
type File struct {
name string
}
func (f *File) print(indentation string) {
fmt.Println(indentation + f.name)
}
func (f *File) clone() Inode {
return &File{name: f.name + "_clone"}
}
folder.go: Prototipo concreto
package main
import "fmt"
type Folder struct {
children []Inode
name string
}
func (f *Folder) print(indentation string) {
fmt.Println(indentation + f.name)
for _, i := range f.children {
i.print(indentation + indentation)
}
}
func (f *Folder) clone() Inode {
cloneFolder := &Folder{name: f.name + "_clone"}
var tempChildren []Inode
for _, i := range f.children {
copy := i.clone()
tempChildren = append(tempChildren, copy)
}
cloneFolder.children = tempChildren
return cloneFolder
}
main.go: Código cliente
package main
import "fmt"
func main() {
file1 := &File{name: "File1"}
file2 := &File{name: "File2"}
file3 := &File{name: "File3"}
folder1 := &Folder{
children: []Inode{file1},
name: "Folder1",
}
folder2 := &Folder{
children: []Inode{folder1, file2, file3},
name: "Folder2",
}
fmt.Println("\nPrinting hierarchy for Folder2")
folder2.print(" ")
cloneFolder := folder2.clone()
fmt.Println("\nPrinting hierarchy for clone Folder")
cloneFolder.print(" ")
}
output.txt: Resultado de la ejecución
Printing hierarchy for Folder2
Folder2
Folder1
File1
File2
File3
Printing hierarchy for clone Folder
Folder2_clone
Folder1_clone
File1_clone
File2_clone
File3_clone