Autumn SALE
Prototyp

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
Na podstawie: Golang By Example

Prototyp w innych językach

Prototyp w języku C# Prototyp w języku C++ Prototyp w języku Java Prototyp w języku PHP Prototyp w języku Python Prototyp w języku Ruby Prototyp w języku Rust Prototyp w języku Swift Prototyp w języku TypeScript