12

我正在阅读有关 Ruby 中的单例的信息。我以前从来没有真正需要使用它们,但我很好奇并决定查找它们,看看我过去是否应该使用它们,或者如果我知道它们是什么,也许我将来可以使用它们用于。

我能想到使用它的唯一时间是:

  • ? 当我需要一个特殊的对象时。示例:“智能”Hash对象,其行为类似于普通的 Ruby 哈希,但有一些额外的怪癖。
  • 当我想让它只存在一个类的实例时。

但是,我不确定我是否需要上述任何一种。

4

4 回答 4

12

请注意,单例模块中的类混合在功能上等同于具有“类”方法的类或模块,并且可以保证初始化调用或内联初始化。比较 Singleton 的这种用法:

require 'singleton'
class Bar
  include Singleton
  attr_reader :jam
  def initialize
    @jam = 42
  end
  def double
    @jam *= 2
  end
end

b1 = Bar.instance
b1.double
b2 = Bar.instance
b2.double
p b1.jam          #=> 168

使用这个无魔法的模块:

module Foo
  @jam = 42
  def self.double
    @jam *= 2
  end
  def self.jam
    @jam
  end
end

Foo.double
Foo.double
p Foo.jam          #=> 168

在这两种情况下,您都有一个维护状态的全局对象。(因为您在全局范围内创建的每个常量,包括类和模块,都是一个全局对象。)

唯一的功能区别是Singleton您将对象的初始化延迟到您第一次请求它。

因此,如果您曾经在一个类或模块上拥有“类”方法,并且您使用这些方法来更改该对象的状态(例如,一个类跟踪从它继承的所有子类),那么您实际上是在使用单例。

于 2012-11-09T22:31:12.563 回答
6

您在 Ruby 中一直使用单例类。事实上,每个对象都有一个单例类。(注意:出于性能原因,单例类实际上只在您第一次访问它们时创建,但这是一种性能优化。语义上,每次您尝试查看单例类时,它都会出现。)

例如,所谓的“类方法”实际上并不存在于 Ruby 中。它们只是类对象的单例类的常规实例方法。(改用“类方法”要容易得多。)

每次使用def foo.bar语法定义方法时,都会将方法添加到foo.

于 2012-11-09T19:09:50.597 回答
5

就像你说的,当你只需要一个类的实例时,就需要一个 Singleton 类。在广泛接受的框架中,Singleton 类的一个很好的例子是 Rails Logger 类。

于 2012-11-09T19:02:54.823 回答
1

你的第二个要点是正确的。将单例类视为完全静态的对象。ruby 中的 Boolean 和 Null 对象就是示例。

于 2012-11-09T19:11:14.360 回答