在Ruby中防止重复的对象
这不完全是单身,但它很接近,所以我认为这很常见。 我有一个类(Foo),其中实例对应于具有唯一ID的外部数据结构。 我想确保没有两个Foo实例可以拥有相同的ID - 如果使用相同的ID值调用构造函数,使用该ID的原始Foo实例,并且所有其他值都会被简单更新。 换句话说,就像:
class Foo
def initialize(id, var1, var2)
if Foo.already_has? id
t = Foo.get_object(id)
t.var1 = var1
t.var2 = var2
return t
else
@var1 = var1
@var2 = var2
end
end
我可以想到两种方法来做到这一点:
我可以将所有Foo实例的数组保存为一个类级变量,然后在初始化方法结束时调用foo_instances.push(self)。 这让我觉得很难看。
我相信Ruby已经对一些数组中的每个类的实例进行了跟踪 - 如果是的话,是否可以访问,并且它会比#1更好吗?
??? (Ruby似乎支持一些漂亮的[meta-]编程技巧,所以如果已经有一个完整的方法来完成这个工作,我就不会感到惊讶了。
您可以在您的对象中重写Foo.new
,然后在其中执行任何您想要的操作:
class Foo
def self.new(id, var1, var2)
return instance if instance = self.lookup
instance = self.allocate
instance.send :initialize, var1, var2
return self.store(instance)
end
end
显然,你也可以使用不同的类方法来获取对象; 使initialize
方法专用于帮助阻止意外分配。
这样你每个ID只有一个实例,这通常比你提出的模式少得多。
你仍然需要实现store
和lookup
位,并且没有什么比你的类中的Hash
或Array
更好。
你想考虑将你存储在你的类中的东西包装在WeakRef实例中,但仍然返回真实的对象。 通过这种方式,课程可以强制实施独特性,而不会限制每次使用的每个ID始终保留在内存中。
这不适合你的情况的每一个版本,但对某些人来说当然是适当的。 一个例子:
# previous code omitted ...
return store(instance)
end
def self.store(instance)
@instances ||= {}
@instances[instance.id] = WeakRef.new(instance)
instance
end
def self.lookup(id)
@instances ||= {}
if weakref = @instances[id] and weakref.weakref_alive?
return weakref.__getobj__ # the wrapped instance
else
return nil
end
end
链接地址: http://www.djcxy.com/p/95433.html