【问题标题】:Observer pattern and stateful observable paradigm观察者模式和有状态的可观察范式
【发布时间】:2015-02-15 00:03:58
【问题描述】:

在 Android 应用程序的开发过程中,我遇到了这个我目前无法解决的设计难题。我将不胜感激任何想法、解决方法或干净的解决方案:) 我会尽量简化它:

一切都从一个通用的观察者模式实现开始。有一个主题在其公共方法调用时改变状态;并且有观察者对这些变化做出相应的反应。 在这种情况下,主题是一个 STATEFUL 主题,这意味着它有一个内部状态控制器(一个 int),它像自动机一样变化。每次它的状态改变时,它都会像往常一样通知观察者:

  • client -> subject.anyMethod() //将主体状态更改为状态 X
  • subject -> notifyObservers(newState) // 主题通知新状态 X
  • observer -> subject.getData() // 获取数据

但现在想想这种情况:

  • client -> subject.anyMethod() //将主体状态更改为状态 X
  • subject -> notifyObservers(X) // 主题 FIRST 通知瀑布
  • observerA -> subject.anyMethod() //根据状态 Y 改变主题
  • subject -> notifyObservers(Y) // 启动第二个通知瀑布

现在会发生什么,作为第二个瀑布的结果,下一个观察者(假设是观察者 B)将收到状态 Y(来自最后一个第二个瀑布)的通知,并采取相应的行动,当这个第二个瀑布完成后,PC(程序计数器)将继续执行第一个通知瀑布,并重新通知观察者 B 旧状态 X。这会产生两个主要问题:第一个问题是,观察者 B 以错误的顺序收到新状态的通知(第一个状态 Y,然后状态 X 当它应该是相反的方式时)第二个也是最重要的,即使以错误的顺序通知,当观察者 B 收到新状态 X 的通知时,它是完全错误的,因为主题真实状态是 Y;这会产生很多问题。

您可能已经意识到,这种情况发生在观察者提交主题状态更改时,当它收到通知而不是仅从主题中获取数据时。我将不胜感激任何其他模式或解决方案。还要澄清一下,只有一个线程。

提前致谢。

【问题讨论】:

    标签: java oop design-patterns uml observer-pattern


    【解决方案1】:

    您需要的是某种同步状态传播的信号量。当subject 传播状态更改时,它首先设置一个信号量,该信号量将锁定subject 的任何进一步状态更改(或简单地传播状态更改)。这也可以通过subject 观察者模式内的堆栈来实现。只有在所有客户端都被告知状态变化后,信号量才会被释放。这样可以保证状态更改的发送按照它们在subject 上执行的顺序到达所有客户端。

    如果您使用状态机对上述内容进行建模,您将使用历史状态机。

    【讨论】:

      【解决方案2】:

      经过几个小时的思考,我想我找到了一个可能的解决方案。这与 Thoms Kilian 的建议有关。关键是某种 post 方法,它将那些改变主题状态的方法排队。一种可能的实现是使用处理程序并将这些方法发布到主线程(请记住没有更多线程):

      client -> subject.anyMethod() //changes subject state to state X
      subject -> handler.post(anyMethod())
      //nothing to do, so post is executed
      subject -> notifyObservers(X) // subject FIRST notification waterfall
      observerA -> subject.anyMethod() //changes subject to state Y
      //here comes the change
      subject -> handler.post(anyMethod())
      //pc keeps sending rest of notifications before executing the posted runnable and the second waterfall
      

      这样,所有观察者在更改时都可以访问相同的状态并将未来的事件排队:)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-02-12
        • 1970-01-01
        • 2016-02-20
        • 2023-04-10
        • 2012-07-09
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多