GoLang设计模式12 - 空对象模式
空对象设计模式是一种行为型设计模式,主要用于应对空对象的检查。使用这种设计模式可以避免对空对象进行检查。也就是说,在这种模式下,使用空对象不会造成异常。
空对象模式的组件包括:
- Entity:接口,定义了子struct需要实现的方法
- ConcreteEntity:实现了Entity 的具体struct
- NullEntity:这个就表示了空对象,虽然也实现了Entity接口,但它的值都是空的
- Client:这个类会获取Entity接口实现类的实例并使用它。这里并不关注实现类是
ConcreteEntity
还是NullEntity
,对二者会进行相同的处理。
用个例子来说一下:假设有一所大学,大学有多个系,每个系都有一定数量的教授。
系(department)可以用一个接口来表示:
1
2
3
4
5
|
type department interface { getNumberOfProfessors() int getName() string } |
大学(college)也是一个接口:
1
2
3
|
type college struct { departments []department } |
现在假设有一个机构想统计下大学每个系的教授数量。
在这个例子里,假设大学里没有某个系,我们就会用到空对象模式。这里定义了一个nullDepartment
来表示不存在的系。
nullDepartment.go:
1
2
3
4
5
6
7
8
9
10
11
|
type nullDepartment struct { numberOfProfessors int } func (c *nullDepartment) getNumberOfProfessors() int { return 0 } func (c *nullDepartment) getName() string { return "nullDepartment" } |
统计的代码在agency.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
25
26
27
28
29
30
31
32
33
34
|
func main() { college1 := createCollege1() college2 := createCollege2() totalProfessors := 0 departmentArray := []string{ "computerScience" , "mechanical" , "civil" , "electronics" } for _, departmentName := range departmentArray { d := college1.getDepartment(departmentName) totalProfessors += d.getNumberOfProfessors() } fmt.Printf( "Total number of professors in college1 is %d\n" , totalProfessors) //Reset the professor count totalProfessors = 0 for _, departmentName := range departmentArray { d := college2.getDepartment(departmentName) totalProfessors += d.getNumberOfProfessors() } fmt.Printf( "Total number of professors in college2 is %d\n" , totalProfessors) } func createCollege1() *college { college := &college{} college.addDepartment( "computerScience" , 4) college.addDepartment( "mechanical" , 5) return college } func createCollege2() *college { college := &college{} college.addDepartment( "computerScience" , 2) return college } |
注意这段代码:
- agency.go 并不关心某个系在大学里是否存在。当这个系不存在时,大学只需要返回一个
nullDepartment
对象即可 - agency.go 对
nullDepartment
对象和其他department
实现类的对象做了相同处理,这之中不需要对空值进行检查,直接调用getNumberOfProfessors()
就可以了
以上就是使用空对象模式的好处了。
下面是其他的代码。
college.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
25
|
type college struct { departments []department } func (c *college) addDepartment(departmentName string, numOfProfessors int) { if departmentName == "computerScience" { computerScienceDepartment := &computerScience{numberOfProfessors: numOfProfessors} c.departments = append(c.departments, computerScienceDepartment) } if departmentName == "mechanical" { mechanicalDepartment := &mechanical{numberOfProfessors: numOfProfessors} c.departments = append(c.departments, mechanicalDepartment) } return } func (c *college) getDepartment(departmentName string) department { for _, department := range c.departments { if department.getName() == departmentName { return department } } //Return a null department if the department doesn't exits return &nullDepartment{} } |
计算机系,computerscience.go:
1
2
3
4
5
6
7
8
9
10
11
|
type computerScience struct { numberOfProfessors int } func (c *computerScience) getNumberOfProfessors() int { return c.numberOfProfessors } func (c *computerScience) getName() string { return "computerScience" } |
数学系,mechanical.go:
1
2
3
4
5
6
7
8
9
10
11
|
type mechanical struct { numberOfProfessors int } func (c *mechanical) getNumberOfProfessors() int { return c.numberOfProfessors } func (c *mechanical) getName() string { return "mechanical" } |
执行agency.go,输出内容如下:
1
2
|
Total number of professors in college1 is 9 Total number of professors in college2 is 2 |
代码已上传至GitHub: zhyea / go-patterns / null-object-pattern
End!!
仅是学习笔记,难免出错,望不吝指点
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)