
Prototyp w języku Go
Prototyp To kreacyjny wzorzec projektowy pozwalający klonować obiekty — również te złożone — bez konieczności sprzęgania z ich klasami.
Wszystkie klasy prototyp powinny mieć wspólny interfejs który pozwoli kopiować ich obiekty nawet gdy nie zna się ich konkretnych klas. Obiekty-prototypy mogą tworzyć kompletne kopie, ponieważ pola prywatne danej klasy są dostępne dla innych obiektów tej samej klasy.
Przykład koncepcyjny
Spróbujmy pojąć wzorzec Prototyp na przykładzie odnoszącym się do systemu plików systemu operacyjnego. System plików jest rekursywny: foldery zawierają pliki i inne foldery, które również mogą zawierać pliki i foldery i tak dalej.
Każdy plik i folder można przedstawić stosując interfejs inode
. Interfejs inode
zawiera także funkcję clone
.
Zarówno struktury file
jak i folder
implementują funkcje print
i clone
gdyż są one typu inode
. Zwróćmy też uwagę, że funkcja clone
w file
i w folder
zwraca kopię — odpowiednio — pliku lub folderu. W momencie klonowania do pola nazwy dołączamy słowo kluczowe “_clone”.
inode.go: Prototype interface
package main
type Inode interface {
print(string)
clone() Inode
}
file.go: Concrete prototype
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: Concrete prototype
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: Kod klienta
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: Wynik działania
Printing hierarchy for Folder2
Folder2
Folder1
File1
File2
File3
Printing hierarchy for clone Folder
Folder2_clone
Folder1_clone
File1_clone
File2_clone
File3_clone