Глянь мой новый курс по Git! Привет! Глянь мой новый курс по Git! Привет! Глянь мой новый курс по Git на GitByBit.com! Привет! Хочешь круто подтянуть Git? Глянь мой новый курс на GitByBit.com!
Прототип

Прототип на 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
По материалам: Golang By Example

Прототип на других языках программирования

Прототип на C# Прототип на C++ Прототип на Java Прототип на PHP Прототип на Python Прототип на Ruby Прототип на Rust Прототип на Swift Прототип на TypeScript