go设计模式教程之:观察值模式


作者:键盘武者
原文链接:https://blog.csdn.net/HierarchCharles?type=blog

观察者模式的定义

观察者模式(Observer Pattern),也称为发布-订阅(Publish-Subscribe)模式,是一种常用的设计模式,属于行为型模式。这种模式用于建立对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并自动更新。

观察者模式通常涉及以下两类角色:

  1. 主题(Subject):主题是观察者模式中的核心。它维护一系列观察者,提供用于增加或删除观察者的方法,并在其内部状态发生变化时通知所有观察者。

  2. 观察者(Observer):观察者订阅主题的状态变化。每个观察者都必须实现一个更新接口,以便在主题状态变化时接收更新。

观察者模式的工作流程通常如下:

  • 观察者向主题注册,表明它们对主题状态的变化感兴趣。
  • 主题在其内部状态发生变化时,通过调用观察者的更新方法来通知所有注册的观察者。
  • 观察者收到通知后,可以相应地更新自己或执行特定操作。

观察者模式的优点包括:

  • 支持广播通信:主题可以无差别地通知所有感兴趣的观察者,无需关心它们的具体类型。
  • 解耦:主题不需要知道观察者的具体实现,只需要知道它实现了观察者接口。这有助于降低系统各部分之间的耦合度。
  • 动态订阅:观察者可以根据需要动态地订阅或取消订阅主题。

然而,它也有一些缺点,如:

  • 可能导致更新的过度调用:在某些情况下,当主题状态频繁变化时,可能会导致大量的更新通知,从而影响性能。
  • 观察者与主题之间的依赖关系:虽然减少了耦合,但观察者仍然需要了解它们需要更新的内容。

观察者模式广泛应用于实现事件处理系统、GUI工具、数据监视等场景。

go实现观察值模式

在Go语言中实现观察者模式,我们可以定义两个主要的接口:ObserverSubjectObserver 接口将包含一个方法,该方法在被通知时调用。Subject 接口则包含添加、删除和通知观察者的方法。以下是一个简单的实现示例:

  1. Observer 接口 - 这个接口定义了一个 Update 方法,当 Subject 发生变化时,该方法将被调用。

  2. Subject 接口 - 这个接口定义了 Attach, DetachNotify 方法。Attach 用于添加新的观察者,Detach 用于移除观察者,而 Notify 用于通知所有注册的观察者。

  3. 具体的 Subject 实现 - 这是一个实现了 Subject 接口的具体类。它将维护观察者列表,并在状态发生变化时通知它们。

  4. 具体的 Observer 实现 - 实现了 Observer 接口的具体类,当收到通知时做出相应的反应。

下面是用Go实现的代码示例:

package main

import (
	"fmt"
)

// Observer 接口
type Observer interface {
	Update(string)
}

// Subject 接口
type Subject interface {
	Attach(Observer)
	Detach(Observer)
	Notify()
}

// ConcreteSubject 是 Subject 的具体实现
type ConcreteSubject struct {
	observers []Observer
	state     string
}

// Attach 方法添加新的观察者
func (cs *ConcreteSubject) Attach(o Observer) {
	cs.observers = append(cs.observers, o)
}

// Detach 方法移除观察者
func (cs *ConcreteSubject) Detach(o Observer) {
	var indexToRemove int
	for i, observer := range cs.observers {
		if observer == o {
			indexToRemove = i
			break
		}
	}
	cs.observers = append(cs.observers[:indexToRemove], cs.observers[indexToRemove+1:]...)
}

// Notify 方法通知所有观察者
func (cs *ConcreteSubject) Notify() {
	for _, observer := range cs.observers {
		observer.Update(cs.state)
	}
}

// SetState 改变状态并通知观察者
func (cs *ConcreteSubject) SetState(state string) {
	cs.state = state
	cs.Notify()
}

// ConcreteObserver 是 Observer 的具体实现
type ConcreteObserver struct {
	id int
}

// Update 方法是观察者接收通知的方式
func (co *ConcreteObserver) Update(state string) {
	fmt.Printf("Observer %d received new state: %s\n", co.id, state)
}

// 主函数
func main() {
	subject := &ConcreteSubject{}

	observer1 := &ConcreteObserver{id: 1}
	observer2 := &ConcreteObserver{id: 2}

	subject.Attach(observer1)
	subject.Attach(observer2)

	subject.SetState("some state")

	subject.Detach(observer1)

	subject.SetState("another state")
}

在这个示例中,当 ConcreteSubject 的状态发生变化时,它将通知所有已注册的 ConcreteObserver。观察者模式在需要实现事件监听和通知机制的场景中非常有用。

go哪些框架使用了观察者模式

在Go语言中,有几个流行的框架和库使用了观察者模式,这主要体现在事件处理、消息传递、数据变更通知等方面。以下是一些常见的Go框架和库,它们在各自的功能或设计中实现了观察者模式:

  1. Revel:Revel 是一个高效的Web框架,它在内部使用了观察者模式来处理诸如HTTP请求、路由事件等。Revel 允许开发者通过定义不同的处理函数来“订阅”这些事件,从而对特定事件做出响应。

  2. Beego:Beego 是另一个Go语言的Web框架,它在某些方面使用了观察者模式。例如,Beego的日志系统可以看作是一个观察者,它“观察”应用中发生的各种事件,并根据日志级别和配置来记录这些事件。

  3. GORM:GORM 是一个流行的Go ORM框架,它提供了Hooks功能,这可以看作是观察者模式的一种实现。开发者可以在数据库操作(如插入、更新、删除)之前或之后挂载自定义函数,这些函数相当于观察者,它们在特定事件发生时被调用。

  4. Go-Micro:在微服务领域,Go-Micro 框架使用观察者模式来实现服务间的事件驱动通信。它允许服务注册事件监听器,当特定事件发生时,这些监听器会被通知。

  5. nsq:nsq 是一个实时分布式消息平台,虽然不是一个框架,但它的设计充分体现了观察者模式。生产者发布消息到主题(Topic),而消费者订阅这些主题以接收消息,这正是观察者模式的典型应用场景。

这些框架和库使用观察者模式来提高模块间的解耦,允许开发者以灵活的方式响应系统内部的各种事件。观察者模式的这种使用方式提高了代码的可维护性和可扩展性。

  • 13
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
以下是几种常见的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 } ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值