首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

Observable

观察者模式(也称为发布/订阅)为一个对象提供了一种简单的机制,用于在状态发生变化时通知一组感兴趣的第三方对象。

机制

通知类混入Observable模块中,该模块提供了管理关联观察器对象的方法。

可观察对象必须:

  • 断言它有 #changed
  • 调用 #notify_observers

观察者使用#add_observer订阅更新,它还指定通过notify_observers调用的方法。notify_observers的默认方法是更新。

下面的例子很好地证明了这一点。一Ticker,在运行时,不断地接收股票Price为它@symbol。A Warner是价格的一般观察者,并且两个警告者被证明是a WarnLow和a WarnHigh,如果价格低于或高于他们设定的限制,它们分别发出警告。

update回调使华纳而不被显式调用运行。该系统由Ticker几名观察员组成,观察员在没有顶级代码干扰的情况下尽自己的职责。

请注意,发布者和订阅者(??观察者和观察者)之间的合同未被声明或执行。在Ticker发布时间和价格,以及华纳接收。但如果你不确保你的合同是正确的,没有别的可以警告你。

代码语言:javascript
复制
require "observer"

class Ticker          ### Periodically fetch a stock price.
  include Observable

  def initialize(symbol)
    @symbol = symbol
  end

  def run
    last_price = nil
    loop do
      price = Price.fetch(@symbol)
      print "Current price: #{price}\n"
      if price != last_price
        changed                 # notify observers
        last_price = price
        notify_observers(Time.now, price)
      end
      sleep 1
    end
  end
end

class Price           ### A mock class to fetch a stock price (60 - 140).
  def self.fetch(symbol)
    60 + rand(80)
  end
end

class Warner          ### An abstract observer of Ticker objects.
  def initialize(ticker, limit)
    @limit = limit
    ticker.add_observer(self)
  end
end

class WarnLow < Warner
  def update(time, price)       # callback for observer
    if price < @limit
      print "--- #{time.to_s}: Price below #@limit: #{price}\n"
    end
  end
end

class WarnHigh < Warner
  def update(time, price)       # callback for observer
    if price > @limit
      print "+++ #{time.to_s}: Price above #@limit: #{price}\n"
    end
  end
end

ticker = Ticker.new("MSFT")
WarnLow.new(ticker, 80)
WarnHigh.new(ticker, 120)
ticker.run

生产:

代码语言:javascript
复制
Current price: 83
Current price: 75
--- Sun Jun 09 00:10:25 CDT 2002: Price below 80: 75
Current price: 90
Current price: 134
+++ Sun Jun 09 00:10:25 CDT 2002: Price above 120: 134
Current price: 134
Current price: 112
Current price: 79
--- Sun Jun 09 00:10:25 CDT 2002: Price below 80: 79

公共实例方法

add_observer(observer, func=:update) Show source

observer作为观察者添加到此对象上。以便它会收到通知。

observer

将被通知更改的对象。

func

符号命名当Observable发生更改时将要调用的方法。

此方法必须返回true observer.respond_to?并且将*arg在notify_observers被调用时接收,其中*arg值是由此Observable传递给notify_observers的值

代码语言:javascript
复制
# File lib/observer.rb, line 127
def add_observer(observer, func=:update)
  @observer_peers = {} unless defined? @observer_peers
  unless observer.respond_to? func
    raise NoMethodError, "observer does not respond to `#{func}'"
  end
  @observer_peers[observer] = func
end

changed(state=true) Show source

设置此对象的更改状态。只有当改变的通知将被发送statetrue

state

布尔值,指示此Observable的状态已更改。

代码语言:javascript
复制
# File lib/observer.rb, line 168
def changed(state=true)
  @observer_state = state
end

changed?() Show source

如果自上次notify_observers调用后更改了此对象的状态,则返回true。

代码语言:javascript
复制
# File lib/observer.rb, line 176
def changed?
  if defined? @observer_state and @observer_state
    true
  else
    false
  end
end

count_observers() Show source

返回与此对象关联的观察者的数量。

代码语言:javascript
复制
# File lib/observer.rb, line 154
def count_observers
  if defined? @observer_peers
    @observer_peers.size
  else
    0
  end
end

delete_observer(observer) Show source

observer作为观察者移除此对象,以便它不再接收通知。

observer

这个Observable的观察者

代码语言:javascript
复制
# File lib/observer.rb, line 140
def delete_observer(observer)
  @observer_peers.delete observer if defined? @observer_peers
end

delete_observers() Show source

删除与此对象关联的所有观察者。

代码语言:javascript
复制
# File lib/observer.rb, line 147
def delete_observers
  @observer_peers.clear if defined? @observer_peers
end

notify_observers(*arg) Show source

如果该对象的状态改变,通知观察者状态改变true

这将调用add_observer中传递的方法*arg。然后将更改的状态设置为false

*arg

任何传递给观察者的参数。

代码语言:javascript
复制
# File lib/observer.rb, line 192
def notify_observers(*arg)
  if defined? @observer_state and @observer_state
    if defined? @observer_peers
      @observer_peers.each do |k, v|
        k.send v, *arg
      end
    end
    @observer_state = false
  end
end

扫码关注腾讯云开发者

领取腾讯云代金券

http://www.vxiaotou.com