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!!

posted @   robin·张  阅读(309)  评论(0编辑  收藏  举报
编辑推荐:
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示