![Прототип](/images/patterns/cards/prototype-mini.png?id=bc3046bb39ff36574c08d49839fd1c8e)
Прототип на Go
Прототип — це породжуючий патерн, який дозволяє копіювати об’єкти будь-якої складності без прив’язки до їхніх конкретних класів.
Усі класи-Прототипи мають спільний інтерфейс. Тому ви можете копіювати об’єкти, не звертаючи уваги на їхні конкретні типи та бути завжди впевненими в тому, що отримаєте точну копію. Клонування здійснюється самим об’єктом-прототипу, що дозволяє йому скопіювати значення всіх полів, навіть приватних.
Концептуальний приклад
Давайте спробуємо розібрати патерн Прототип, використовуючи за приклад файлову систему ОС. Файлова система є рекурсивною — папки містять файли та інші папки, які, в свою чергу, можуть містити файли та папки, і так далі.
Кожен файл і папка можуть бути представлені інтерфейсом inode
. Він має функцію clone
.
Обидві структури файлу й папки — file
і folder
— реалізують функції print
і clone
, оскільки вони мають тип inode
. Також, зверніть увагу на функцію clone
в file
і folder
. Функція clone
в обох випадках повертає копію відповідного файлу або папки. Під час клонування ми додаємо ключове слово «_clone» в поле імені.
inode.go: Інтерфейс прототипа
package main
type Inode interface {
print(string)
clone() Inode
}
file.go: Конкретний прототип
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: Конкретний прототип
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: Клієнтський код
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: Результат виконання
Printing hierarchy for Folder2
Folder2
Folder1
File1
File2
File3
Printing hierarchy for clone Folder
Folder2_clone
Folder1_clone
File1_clone
File2_clone
File3_clone