Golang与设计模式-Iterator迭代器模式

迭代器模式在Java和C#中常用到的行为型设计模式,这种模式主要用于对于集合(Aggregate)的有序访问。

一般情况下Golang的开发中是不需要使用到的,像Slice跟Array都可以通过for...range...来完成遍历。但不是说一定就用不上哦。

场景

我有一个书架(BookShelf),书架内摆放了很多书籍(Book),我想要不直接暴露BookShelf内部数据的情况下,获取书架上所有的书籍信息。

如果应用上迭代器模式我们该如何实现呢?

很简单,当我们想要获取所有书籍信息时,直接获取BookShelf的迭代器(Iterator),我们通过对迭代器的方法Next()调用来遍历获取书籍信息。迭代器的职责就是遍历数据集合的。

接口

首先,我们知道迭代器模式主要适用于数据集合,那么我们就可以定义一个集合(Aggregate)接口,这个接口只有一个方法,就是返回给我们一个迭代器(Iterator)。

// 集合接口
type Aggregate interface {
	// 返回一个迭代器
	GetIterator() Iterator
}

然后,我们还需要一个定义一个迭代器(Iterator)接口,这个接口有两个方法,分别是 HasNext()bool,判断是否还有值;Next()interface{},返回下一个值。

// 迭代器接口
type Iterator interface {
	// 判断是否还有值
	HasNext() bool
	// 取下一个值
	Next() interface{}
}

实现

接下来我们还需要定义一个Book结构体,并分别定于实现了Aggregate接口书架类型BookShelf,以及实现了 Iterator接口的 BookShelfIterator

// 书
type Book struct {
	// 名字
	Name string
	// 作者
	Author string
}

Book只有两个string类型字段,书名Name,作者Author。

// 书架,一个存放书籍的集合
type BookShelf struct {
	books []Book
}

// 书架实现集合接口
func (bs *BookShelf) GetIterator() Iterator {
	// 每次都会创建一个新的迭代器,从 index=0 位置开始遍历
	return &BookShelfIterator{bookShelf: bs}
}

书架BookShelf中有一个书的集合Books。并且实现了集合(Aggregate)接口的 返回迭代器Iterator的方法。

// 书架迭代器
type BookShelfIterator struct {
	// 当前遍历位置
	index int
	// 所指向书架
	bookShelf *BookShelf
}

// 书架迭代器实现迭代器接口
func (i *BookShelfIterator) HasNext() bool {
	return i.index < len(i.bookShelf.books)
}

// 书架迭代器实现迭代器接口
func (i *BookShelfIterator) Next() interface{} {
	book := i.bookShelf.books[i.index]
	i.index++

	return book
}

书架迭代器BookShelfIterator实现 Iterator接口的两个方法。

测试

接下来我们测试一下代码:

func main() {
	// 声明一个书架对象,并添加一些书籍
	bookShelf := &BookShelf{
		books: []Book{
			{Name: "以太坊技术详解与实战", Author: "闫莺,郑恺,郭众鑫"},
			{Name: "大话代码架构", Author: "田伟,郎小娇"},
			{Name: "GO语言公链开发实战", Author: "郑东旭,杨明珠,潘盈瑜,翟萌"},
			{Name: "区块链原理、设计与应用", Author: "杨保华,陈昌"},
			{Name: "精通区块链智能合约开发", Author: "熊丽兵"},
			{Name: "C程序设计", Author: "谭浩强"},
		},
	}

	// 获取书架的迭代器
	iterator := bookShelf.GetIterator()

	// 遍历,直到没有下一本书(HasNext == flase)
	for iterator.HasNext() {
		book := iterator.Next().(Book)
		fmt.Printf("书名:%s, 作者:%s \n", book.Name, book.Author)
	}
}

运行结果:

代码已上传Github:LyonNee/design_patterns_with_go: 基于Golang实现的设计模式代码 (github.com)

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是几种常见的Golang设计模式: 1. 工厂模式(Factory Pattern):用于创建对象的模式,通过定义一个创建对象的接口来实现对象的实例化。 ```go type Shape interface { Draw() } type Circle struct{} func (c *Circle) Draw() { fmt.Println("Drawing a circle") } type Rectangle struct{} func (r *Rectangle) Draw() { fmt.Println("Drawing a rectangle") } type ShapeFactory struct{} func (sf *ShapeFactory) GetShape(shapeType string) Shape { if shapeType == "circle" { return &Circle{} } else if shapeType == "rectangle" { return &Rectangle{} } return nil } func main() { factory := &ShapeFactory{} circle := factory.GetShape("circle") circle.Draw() // 输出:Drawing a circle rectangle := factory.GetShape("rectangle") rectangle.Draw() // 输出:Drawing a rectangle } ``` 2. 单例模式(Singleton Pattern):确保一个类只有一个实例,并提供一个全局访问点。 ```go type Singleton struct{} var instance *Singleton func GetInstance() *Singleton { if instance == nil { instance = &Singleton{} } return instance } func main() { singleton1 := GetInstance() singleton2 := GetInstance() fmt.Println(singleton1 == singleton2) // 输出:true } ``` 3. 观察者模式(Observer Pattern):定义了一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖它的对象都会得到通知并自动更新。 ```go type Subject struct { observers []Observer } func (s *Subject) Attach(observer Observer) { s.observers = append(s.observers, observer) } func (s *Subject) Notify() { for _, observer := range s.observers { observer.Update() } } type Observer interface { Update() } type ConcreteObserver struct{} func (co *ConcreteObserver) Update() { fmt.Println("Observer is updated") } func main() { subject := &Subject{} observer := &ConcreteObserver{} subject.Attach(observer) subject.Notify() // 输出:Observer is updated } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值