GoLang設計模式05 - 原型模式

robin·張發表於2021-09-11

原型模式也是一種建立型模式,它可以幫助我們優雅地建立物件的拷貝。在這種設計模式裡面,將克隆某個物件的職責交給了要被克隆的這個物件。被克隆的物件需要提供一個clone()方法。通過這個方法可以返回該物件的拷貝。

原型模式的使用場景:

  1. 建立新物件的操作比較耗資源(如資料庫操作)或代價比較高時。比較起從頭建立新物件,克隆物件明顯更加可取
  2. 要被克隆的物件建立起來比較複雜時:比如物件克隆的過程中存在深度拷貝或分層拷貝時;又比如要被克隆的物件存在無法被直接訪問到的私有成員時。

原型模式的UML類圖:

在日常中我們遇到的包含新建、copy這些操作的場景最多的就是常規的檔案系統操作了。所以接下來會以檔案系統為例介紹下原型模式。

在檔案系統中存在檔案(file)和資料夾(folder)兩類實體。其中資料夾中又可以包含檔案和子資料夾。這裡我們用一個inode介面來表示檔案和資料夾。為了表示常見的複製操作,在inode介面中還定義了一個clone()函式。

inode.go

type inode interface {
	print(string)
	clone() inode
}

file 和 folder兩個struct實現了inode介面。

file.go

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

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
}

filefolder兩個struct都實現了print()clone()函式,根據go語言的約定,可以認為它們都繼承了inode介面,即可以認為它們是inode型別了。這兩者的clone()函式會返回其各自相關的檔案或資料夾的備份。為了和原有的檔案/資料夾作區分,我們在複製的物件的名稱上新增了“_clone”這樣的標記。

來看看main函式是怎樣的,main.go:

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("  ")
}

執行結果是:

Printing hierarchy for Folder2
  Folder2
    Folder1
        File1
    File2
    File3

Printing hierarchy for clone Folder
  Folder2_clone
    Folder1_clone
        File1_clone
    File2_clone
    File3_clone

程式碼已上傳至GitHub, 地址: zhyea / go-patterns / prototype-pattern

END!

相關文章