春のセール
Prototype

Prototype を Go で

Prototype 生成に関するデザインパターンの一つで 特定のクラスに結合することなく オブジェクト たとえ複雑なオブジェクトでも のクローン作成を可能とします

プロトタイプのクラス全部には 共通するインターフェースが必要です これにより 具象クラスが不明であってもオブジェクトを複製することが可能となります プロトタイプ・オブジェクトが 完全なコピーを生成できるのは 同じクラスのオブジェクト同士が非公開フィールドを互いにアクセスできるからです

概念的な例

オペレーティング・システムのファイル・システムに基づいた例を使い Prototype パターンを調べてみましょう OS のファイル・システムは再帰的です フォルダーにはファイルとフォルダーが含まれており そのフォルダーには ファイルとフォルダーも含まれている といった具合です

個々のファイルおよびフォルダーは inode インターフェースで表現されます inode インターフェースには clone 関数があります

file 構造体と folder 構造体の両方とも inode 型をしているので print 関数と clone 関数を実装します filefolder の両方に clone 関数があることにも注目してください 両方に含まれる clone 関数は それぞれファイルかフォルダーのコピーを返します クローン作成にあたり name フィールドに _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

他言語での Prototype

Prototype を C# で Prototype を C++ で Prototype を Java で Prototype を PHP で Prototype を Python で Prototype を Ruby で Prototype を Rust で Prototype を Swift で Prototype を TypeScript で