我有一个节点网络,每个节点都会影响其他一些节点的状态(想象一个 Excel 电子表格,其单元格值通过公式取决于其他单元格)。
我想知道在 Ruby 中实现这个的最干净的方法是什么?
当然,我可以每个节点有一个进程,但是如果节点数量增加,它将如何执行?而且,我确信有相应的库,但我找不到最新的库。
谢谢你的帮助 !
更新:听起来 EventMachine 可能会完成这项工作......但它似乎更适合少数“节点”
我有一个节点网络,每个节点都会影响其他一些节点的状态(想象一个 Excel 电子表格,其单元格值通过公式取决于其他单元格)。
我想知道在 Ruby 中实现这个的最干净的方法是什么?
当然,我可以每个节点有一个进程,但是如果节点数量增加,它将如何执行?而且,我确信有相应的库,但我找不到最新的库。
谢谢你的帮助 !
更新:听起来 EventMachine 可能会完成这项工作......但它似乎更适合少数“节点”
对于观察者模式来说,这听起来不错。这是 ruby 中的一个示例:
require 'observer'
class Node
attr_accessor :id
@@current_node_id = 0
def initialize
@@current_node_id += 1
id = @@current_node_id
end
include Observable
attr_reader :value
protected
def value=(new_value)
return if @value == new_value
old_value = @value
@value = new_value
changed
notify_observers(id, old_value, @value)
end
end
class ValueNode < Node
def initialize(initial_value)
super()
@value = initial_value
end
def value=(new_value)
super(new_value)
end
end
class SumNode < Node
def initialize(*nodes)
super()
@value = nodes.map(&:value).inject(0, &:+)
nodes.each do |node|
node.add_observer(self)
end
end
def update(id, old_value, new_value)
self.value = self.value - old_value + new_value
end
end
def test
v1 = ValueNode.new 4
v2 = ValueNode.new 8
sum = SumNode.new(v1, v2)
sum2 = SumNode.new(v1, sum)
v2.value = 10
p sum.value
p sum2.value
end
test()
请注意,SumNode
每次请求时不会重新计算 的值 - 而是在更新其值节点之一时更新它。这以递归方式工作,因此内部SumNodes
也触发更新。由于通知包含id
节点的唯一性,因此可以编写更复杂Node
的类型,例如包含公式的类型。
有关Observable 的更多详细信息,请参见http://www.ruby-doc.org/stdlib/libdoc/observer/rdoc/index.html
这听起来类似于经常使用的 Twitter 范例,其中一个用户的更新被推送给它的所有追随者。为了有效地做到这一点,你应该为给定的人存储两个列表:一个是他关注的人,一个是关注他的人。您可以对节点列表执行相同的操作。当一个节点发生变化时,您可以快速查找受该节点影响的节点。当关系消失时,您将需要“转发”列表来了解要从哪些列表中“删除”反向关系。
您可以将这些列表存储在二维数组中,或者存储在 Redis 之类的东西中。我真的不明白 EventMachine 将如何适应。