想象一下,我有一个对象模型:
博客有很多文章,文章有很多评论
想象一下,我还有两个博客,博客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.
在这种情况下,博客B应将注释3更改为“有趣的东西”,并实例化具有与第2条和注释2相同的值的新对象。
递归地移动图形是一个显而易见的解决方案,但逻辑变得复杂。我宁愿不重新发明轮子......有没有一种模式或过程可以做到这一点?
我正在使用Ruby / Rails
答案 0 :(得分:0)
在阅读了有关访客模式的更多信息之后,我决定使用它的Rubyish变体来解决这个问题。
访问者模式允许您将用于遍历层次结构的算法与要在层次结构中的每个节点上执行的代码分开。可以使用map或inject / fold来实现更实用的方法......但是当我想重用运算符时,将它们分成单独的类似乎更容易。
层次结构在每个模型中实现,它应该定义一个返回子节点的“children”方法。
以下是我的实现,基于各种引用,我可以将其包装成gem。
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"?