原型模式也是一种创建型模式,它可以帮助我们优雅地创建对象的拷贝。在这种设计模式里面,将克隆某个对象的职责交给了要被克隆的这个对象。被克隆的对象需要提供一个clone()方法。通过这个方法可以返回该对象的拷贝。

原型模式的使用场景:

  1. 创建新对象的操作比较耗资源(如数据库操作)或代价比较高时。比较起从头创建新对象,克隆对象明显更加可取
  2. 要被克隆的对象创建起来比较复杂时:比如对象克隆的过程中存在深度拷贝或分层拷贝时;又比如要被克隆的对象存在无法被直接访问到的私有成员时。

原型模式的UML类图:

GoLang设计模式05 - 原型模式

在日常中我们遇到的包含新建、copy这些操作的场景最多的就是常规的文件系统操作了。所以接下来会以文件系统为例介绍下原型模式。

在文件系统中存在文件(file)和文件夹(folder)两类实体。其中文件夹中又可以包含文件和子文件夹。这里我们用一个inode接口来表示文件和文件夹。为了表示常见的复制操作,在inode接口中还定义了一个clone()函数。

inode.go

1
2
3
4
type inode interface {
    print(string)
    clone() inode
}

file 和 folder两个struct实现了inode接口。

file.go

1
2
3
4
5
6
7
8
9
10
11
12
13
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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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("  ")
}

运行结果是:

1
2
3
4
5
6
7
8
9
10
11
12
13
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!

 


仅是学习笔记,难免出错,望不吝指点

 
转 https://www.cnblogs.com/amunote/p/15256894.html

原型模式也是一种创建型模式,它可以帮助我们优雅地创建对象的拷贝。在这种设计模式里面,将克隆某个对象的职责交给了要被克隆的这个对象。被克隆的对象需要提供一个clone()方法。通过这个方法可以返回该对象的拷贝。

原型模式的使用场景:

  1. 创建新对象的操作比较耗资源(如数据库操作)或代价比较高时。比较起从头创建新对象,克隆对象明显更加可取
  2. 要被克隆的对象创建起来比较复杂时:比如对象克隆的过程中存在深度拷贝或分层拷贝时;又比如要被克隆的对象存在无法被直接访问到的私有成员时。

原型模式的UML类图:

GoLang设计模式05 - 原型模式

在日常中我们遇到的包含新建、copy这些操作的场景最多的就是常规的文件系统操作了。所以接下来会以文件系统为例介绍下原型模式。

在文件系统中存在文件(file)和文件夹(folder)两类实体。其中文件夹中又可以包含文件和子文件夹。这里我们用一个inode接口来表示文件和文件夹。为了表示常见的复制操作,在inode接口中还定义了一个clone()函数。

inode.go

1
2
3
4
type inode interface {
    print(string)
    clone() inode
}

file 和 folder两个struct实现了inode接口。

file.go

1
2
3
4
5
6
7
8
9
10
11
12
13
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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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("  ")
}

运行结果是:

1
2
3
4
5
6
7
8
9
10
11
12
13
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!