Потрібна крута книжка про патерни та ще й українською? Ось вона »
Прототип

Прототип на 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 + "_clone")
}

func (f *file) clone() inode {
	return &file{name: f.name}
}

folder.go: Конкретний прототип

package main

import "fmt"

type folder struct {
	childrens []inode
	name      string
}

func (f *folder) print(indentation string) {
	fmt.Println(indentation + f.name)
	for _, i := range f.childrens {
		i.print(indentation + indentation)
	}
}

func (f *folder) clone() inode {
	cloneFolder := &folder{name: f.name + "_clone"}
	var tempChildrens []inode
	for _, i := range f.childrens {
		copy := i.clone()
		tempChildrens = append(tempChildrens, copy)
	}
	cloneFolder.childrens = tempChildrens
	return cloneFolder
}

main.go: Клієнтський код

package main

import "fmt"

func main() {
	file1 := &file{name: "File1"}
	file2 := &file{name: "File2"}
	file3 := &file{name: "File3"}

	folder1 := &folder{
		childrens: []inode{file1},
		name:      "Folder1",
	}

	folder2 := &folder{
		childrens: []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

Прототип іншими мовами програмування

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