假设我有一个对象模型:
博客有很多文章,一篇文章有很多评论。
想象一下,我有两个博客,博客A和博客B。
Blog A - Article id 1 - Comment id 1 "fun stuff"
- Article id 2 - Comment id 2 "cool"
和
Blog B - Article id 3 - Comment id 3 "no fun"
我需要比较博客A和博客B的对象图,并根据博客A中对象的值更新博客B。
在这种情况下,Blog B应该将注释3改为“有趣的东西”,并用与第2条和注释2相同的值实例化新对象。
递归遍历图是显而易见的解决方案,但逻辑变得复杂。我不希望在那里重新发明wheel...is模式或流程来实现这一点?
我在使用Ruby/Rails
发布于 2012-11-13 15:58:46
在阅读了更多关于访问者模式的信息之后,我认为它的Rubyish变体是解决这个问题的最合适的方法。
访问者模式允许您将遍历层次结构的算法与在层次结构中的每个节点上执行的代码分开。使用map或inject/折叠实现此操作的一种更实用的方法是possible...but,因为我想重用这些操作符,将它们分解成不同的类似乎更容易。
层次结构在每个模型中实现,该模型应该定义一个返回子模型的“子”方法。
下面是我的实现,基于各种引用,我可以将它包装成一个宝石。
module Visitable
def accept visitor
child_vals = []
if respond_to?(:children)
children.each do |child|
child_vals << child.accept(visitor)
end
end
val = visitor.visit(self)
child_vals.any? ? val + child_vals : val
end
end
class Survey
attr_accessor :name, :children
include Visitable
end
class Category
attr_accessor :name, :children
include Visitable
end
class Question
attr_accessor :name
include Visitable
end
s = Survey.new
s.name = 's1'
c = Category.new
c.name = 'c1'
c2 = Category.new
c2.name = 'c2'
q = Question.new
q.name = 'q1'
q2 = Question.new
q2.name = 'q2'
c.children = [q]
c2.children = [q2]
s.children = [c,c2]
class ReturnVisitor
def visit obj
obj.name
end
end
s.accept(ReturnVistor.new)
-> ['s1', ['c1', ['q1'], ['c2', ['q2']]]]
# "poorly implemented lisp"?
https://stackoverflow.com/questions/13317412
复制相似问题