0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

什么是观察者设计模式?Golang中的观察者模式介绍

马哥Linux运维 来源:稀土掘金 2024-01-08 10:08 次阅读

当涉及到订单处理系统时,观察者设计模式可以用于实现订单状态的变化和通知。在这篇文章中,我们将介绍如何使用Golang来实现观察者设计模式,并提供一个基于订单处理系统的代码示例。

什么是观察者设计模式?

观察者设计模式是一种行为型设计模式,它允许对象之间的松耦合通信。在这种模式中,一个对象(称为主题Subject)维护一组依赖于它的对象(称为观察者Observer)的列表,并在状态改变时自动通知它们。观察者模式可以用于实现事件驱动的系统,其中对象之间的交互是通过事件的发布和订阅来完成的。

应用场景:订单处理系统

在订单处理系统中,订单的状态可能会发生变化,例如创建、支付、发货、取消等。当订单状态发生变化时,我们希望通知相关的观察者进行相应的处理,例如更新库存、发送通知等。

实现观察者设计模式

在Golang中,可以使用channel和goroutine来实现观察者设计模式。

首先,我们定义一个订单结构体,包含订单的基本信息和状态:


type Order struct {
  ID     string
  Status string
}

然后,我们定义一个观察者接口,包含一个Update方法,用于处理订单状态变化的通知:

type Observer interface {
  Update(order *Order, wg *sync.WaitGroup)
}

接下来,我们定义一个主题结构体,使用channel和goroutine来通知观察者:

type Subject struct {
  observers []Observer
}


func (s *Subject) Register(observer Observer) {
  s.observers = append(s.observers, observer)
}


func (s *Subject) Notify(order *Order) {
  wg := sync.WaitGroup{}
  wg.Add(len(s.observers))


  errCh := make(chan error, len(s.observers))


  for _, observer := range s.observers {
    go func(obs Observer) {
      defer wg.Done()


      err := obs.Update(order, &wg)
      if err != nil {
        errCh <- err
      }
    }(observer)
  }


  wg.Wait()
  close(errCh)


  // 处理异常
  for err := range errCh {
    fmt.Println("Error occurred:", err)
  }
}




我们首先创建了一个errCh(类型为chan error)来接收观察者处理过程中可能发生的异常。然后,在每个观察者的goroutine中,我们通过闭包的方式传递observer并在处理完成后检查是否有异常发生。如果有异常,我们将其发送到errCh中。

在Notify方法的最后,我们关闭了errCh通道,并通过range循环来处理所有的异常。

接下来,我们实现两个观察者:库存观察者和通知观察者。

库存观察者用于更新库存状态:


type InventoryObserver struct{}


func (io *InventoryObserver) Update(order *Order, wg *sync.WaitGroup) {
  defer wg.Done()


  // 更新库存状态
  fmt.Printf("Inventory Observer: Order %s status changed to %s
", order.ID, order.Status)
}




通知观察者用于发送通知:


type NotificationObserver struct{}


func (no *NotificationObserver) Update(order *Order, wg *sync.WaitGroup) {
  defer wg.Done()


  // 发送通知
  fmt.Printf("Notification Observer: Order %s status changed to %s
", order.ID, order.Status)
}




最后,我们在主函数中使用观察者模式来处理订单状态变化的通知:


func main() {
  order := &Order{
    ID:     "123",
    Status: "Created",
  }


  subject := &Subject{}
  subject.Register(&InventoryObserver{})
  subject.Register(&NotificationObserver{})


  // 模拟订单状态变化
  order.Status = "Paid"
  subject.Notify(order)


  order.Status = "Shipped"
  subject.Notify(order)
}


我们创建了一个订单对象和一个主题对象,并注册了库存观察者。然后,我们模拟订单状态的变化,通过调用Notify方法并发地通知观察者进行处理。

通过使用channel和goroutine,我们可以实现观察者模式的并发处理,提高系统的性能和响应能力。

使用观察者设计模式的一些优点

松耦合:观察者模式可以将观察者和主题(或被观察者)对象解耦。观察者只需要关注主题的状态变化,而不需要了解具体的实现细节。这样可以使得系统更加灵活和可扩展。

可重用性:通过将观察者和主题对象分离,可以使得它们可以在不同的上下文中重复使用。例如,可以在不同的业务场景中使用相同的观察者来处理不同的主题对象。

易于扩展:当需要添加新的观察者或主题时,观察者模式可以很方便地进行扩展。只需要实现新的观察者或主题对象,并注册到主题对象中即可。

事件驱动:观察者模式适用于事件驱动的系统。当主题对象的状态发生变化时,可以通过触发事件来通知所有的观察者进行相应的处理。

如果不使用观察者设计模式

订单业务可能会以一种更加紧耦合的方式实现。以下是一个示例代码,展示了在没有使用观察者模式的情况下,如何处理订单状态变化的问题:


type Order struct {
  ID     string
  Status string
}


type OrderProcessor struct {
  inventoryObserver    *InventoryObserver
  notificationObserver *NotificationObserver
}


func NewOrderProcessor() *OrderProcessor {
  return &OrderProcessor{
    inventoryObserver:    &InventoryObserver{},
    notificationObserver: &NotificationObserver{},
  }
}


func (op *OrderProcessor) Process(order *Order) {
  // 更新库存
  op.inventoryObserver.Update(order)


  // 发送通知
  op.notificationObserver.Update(order)
}


func main() {
  order := &Order{
    ID:     "123",
    Status: "Created",
  }


  op := NewOrderProcessor()


  // 模拟订单状态变化
  order.Status = "Paid"
  op.Process(order)


  order.Status = "Shipped"
  op.Process(order)
}


在这个示例中,OrderProcessor对象负责处理订单状态变化。它内部包含了InventoryObserver和NotificationObserver对象,并在Process方法中依次调用它们的Update方法来处理订单状态变化。

这种实现方式存在一些问题:

紧耦合:OrderProcessor对象直接依赖于InventoryObserver和NotificationObserver对象。如果需要添加或删除其他观察者,需要修改OrderProcessor的代码,导致代码的可维护性和可扩展性下降。

代码重复:每当有新的观察者需要处理订单状态变化时,都需要在OrderProcessor中添加相应的代码。这样会导致代码的重复和冗余。

可扩展性差:在没有使用观察者模式的情况下,很难在系统中添加新的观察者,因为每次都需要修改OrderProcessor的代码。







审核编辑:刘清

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 处理系统
    +关注

    关注

    0

    文章

    93

    浏览量

    16675

原文标题:Golang中的观察者模式:优化订单处理系统

文章出处:【微信号:magedu-Linux,微信公众号:马哥Linux运维】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    如何观察重复的公告?

    我能够建立和运行“第10天”观察员样本项目。我在另一个DeV板上运行了一个信标,当我启动观察者时,它报告了“不可连接的单向广告”,但是没有新的事件,尽管我知道信标必须定期发布一个广告。作为证据,如果
    发表于 10-14 07:06

    CC2540广播角色和观察者角色切换代码怎么编写?

    希望一个CC2540先通过观察者角色获取其他广播的广播数据,然后在切换为广播角色将这些数据广播给另外一个观察者?这样就需要编程实现观察者
    发表于 03-16 10:27

    RN4020观察者模式无法正常工作怎么回事

    中心,支持MLDP,并使UART流控制R,1//重新引导,使更改生效J,1//观察者模式你对这个问题有什么想法?谢谢,弗朗西斯科
    发表于 04-22 09:03

    属性观察者的特点

    属性观察者,类似于触发器。用来监视属性的除初始化之外的属性值变化,当属性值发生改变时可以对此作出响应。有如下特点: 1,不仅可以在属性值改变后触发didSet,也可以在属性值改变前触发willSet
    发表于 11-04 07:10

    观察者模式在嵌入式编程设计中有何作用

    观察者模式是最常见的模式之一。这种模式提供一种方法来时对象“监听”其他对象,而不需要修改任何数据服务器。在嵌入式领域,这意味着数据能够很容易分享给其他元素。
    发表于 12-22 08:31

    基于观察者模式的屏幕布局控件设计

    观察者模式作为设计模式中行为模式的一种,解决了上述具有一对多依赖关系对象重用问题。文中在分析观察者模式
    发表于 02-13 16:20 4次下载
    基于<b class='flag-5'>观察者</b><b class='flag-5'>模式</b>的屏幕布局控件设计

    Java设计模式分析之观察者

    观察者模式的流程跟报纸订阅方式一致,即:观察者模式=出版+订阅,只是名称不一样,出版
    发表于 09-26 17:36 0次下载

    在 Java8 环境下实现观察者模式的实例分析

    的一个组成部分。目前虽然已经有大量关于观察者模式的文章,但它们都专注于在 Java 的实现,却忽视了开发在Java中使用观察者
    发表于 10-12 16:09 0次下载
    在 Java8 环境下实现<b class='flag-5'>观察者</b><b class='flag-5'>模式</b>的实例分析

    大陆正在研发一款路况观察者应用

    据外媒报道,大陆正在研发一款路况观察者(Road Condition Observer)应用。随着传感器及摄像头技术的愈发成熟,再结合车载流媒体数据,或许能够完成该应用的设计。此外,工程师还将为该应用写入成熟的算法。
    发表于 05-15 11:30 1007次阅读

    GoF设计模式观察者模式

    现在有 2 个服务,Service A 和 Service B,通过 REST 接口通信;Service A 在某个业务场景下调用 Service B 的接口完成一个计算密集型任务,假设接口为 http://service_b/api/v1/domain;该任务运行时间很长,但 Service A 不想一直阻塞在接口调用上。为了满足 Service A 的要求,通常有 2 种方案:
    的头像 发表于 07-25 11:32 1026次阅读

    设计模式行为型:观察者模式

    定义对象之间的一种一对多依赖关系,使得每一个对象发生状态的变化时,其相关依赖对象皆得到通知并被自动更新,又称为发布-订阅模式、模型-视图模式、源-监听器模式或从属
    的头像 发表于 06-07 16:56 672次阅读
    设计<b class='flag-5'>模式</b>行为型:<b class='flag-5'>观察者</b><b class='flag-5'>模式</b>

    观察者模式,超详细!

    观察者模式建议你为发布类添加订阅机制, 让每个对象都能订阅或取消订阅发布事件流。 不要害怕! 这并不像听上去那么复杂。 实际上, 该机制包括 1) 一个用于存储订阅
    的头像 发表于 08-21 16:06 1202次阅读
    <b class='flag-5'>观察者</b><b class='flag-5'>模式</b>,超详细!

    基于观察者模式设计的框架-REB,使代码模块化

    设计模式里面的观察者模式,一直是作者想去设计一套框架来阐述这一个模式,因此REB(Rice Event Broker)就是为了完成观察者
    的头像 发表于 10-17 09:35 663次阅读
    基于<b class='flag-5'>观察者</b><b class='flag-5'>模式</b>设计的框架-REB,使代码模块化

    一文解析BLE观察者模式回调机制

    nRF5 SDK从版本14开始,对事件回调机制做了更新,引入了观察者模式,以解耦不同BLE Layer对BLE事件的回调函数。
    的头像 发表于 11-27 10:07 1028次阅读
    一文解析BLE<b class='flag-5'>观察者</b><b class='flag-5'>模式</b>回调机制

    观察者网:聚焦 RT-Thread睿赛德开发大会发布多个行业应用操作系统 | 媒体视角

    观察者网报道——睿赛德开发大会在2024RT-Thread睿赛德开发大会上,RT-Thread创始人兼CEO熊谱翔隆重发布了程翧车控系统2.0,并详细介绍了该系统的最新特性及其在汽
    的头像 发表于 12-26 19:42 140次阅读
    <b class='flag-5'>观察者</b>网:聚焦 RT-Thread睿赛德开发<b class='flag-5'>者</b>大会发布多个行业应用操作系统 | 媒体视角