Ruby中的双管和单管有什么实际区别吗?

Ruby中的双管和单管有什么实际区别吗?,ruby,singleton,Ruby,Singleton,昨天我读了关于Ruby的文章,并谈到了Singleton的概念,其中提到的Singleton用于避免多次实例化类 我以前不知道这个概念,但当我想达到这个目的时,我创建了一个全局变量,并使用了双管道 例如: 在某些情况下,是否有任何差异或优势可以使Singleton的使用更好?|124;=用于一个值。例如,如果您有一个执行昂贵操作或返回可变值的方法: class Foo def now Time.now end end f = Foo.new f.now #=> 2018-

昨天我读了关于Ruby的文章,并谈到了Singleton的概念,其中提到的Singleton用于避免多次实例化类

我以前不知道这个概念,但当我想达到这个目的时,我创建了一个全局变量,并使用了双管道

例如:


在某些情况下,是否有任何差异或优势可以使Singleton的使用更好?

|124;=
用于一个值。例如,如果您有一个执行昂贵操作或返回可变值的方法:

class Foo
  def now
    Time.now
  end
end

f = Foo.new
f.now #=> 2018-06-21 11:59:56 +0200
f.now #=> 2018-06-21 11:59:59 +0200
f.now #=> 2018-06-21 12:00:02 +0200
如果要缓存该值,
| |=
是您的朋友:

class Foo
  def now
    @now ||= Time.now
  end
end

f = Foo.new
f.now #=> 2018-06-21 11:59:56 +0200
f.now #=> 2018-06-21 11:59:56 +0200
f.now #=> 2018-06-21 11:59:56 +0200
第一个调用调用
Time.now
,并将结果分配给
@now
。后续调用只返回
@now
,而不计算右侧。因此,
Time.now
只调用一次,方法的返回值不再更改

由于
@now
是一个实例变量,因此每个实例存储一个单独的值:

f = Foo.new
f.now #=> 2018-06-21 11:59:56 +0200
f.now #=> 2018-06-21 11:59:56 +0200
f.now #=> 2018-06-21 11:59:56 +0200

g = Foo.new
f.now #=> 2018-06-21 12:00:02 +0200
f.now #=> 2018-06-21 12:00:02 +0200
f.now #=> 2018-06-21 12:00:02 +0200
另一方面,确保给定类(每个进程)有一个(且只有一个)实例,例如:

这是因为
f
g
指的是同一个对象。包括删除通过
新建
分配
创建任何其他实例的功能:

Foo.new      #=> NoMethodError
Foo.allocate #=> NoMethodError

如果变量未定义或包含假值(nil或false),Ruby中的
| |=
运算符将为变量设置一个值

这通常用于记录方法返回值,以减少不必要的重新计算:

class Foo
  def value
    @value ||= 1+1
  end
end

Foo.new.value # @value was undefined so it set to 1+1 = 2
Foo.new.value # @value was already defined so return it instead of recalculating
单例类是一个只能有一个实例的类

常规非单例类:

class Foo
end

# create two instances:
foo1 = Foo.new
foo2 = Foo.new

foo1 == foo2 # => false 
require 'singleton'
class Foo
  include Singleton

  def test
    "hello"
  end
end

# you can't create an instance:
foo = Foo.new # => NoMethodError (private method `new' called for Foo:Class)

# there is one global instance:
foo1 = Foo.instance
foo2 = Foo.instance
foo1 == foo2 # => true

# the Singleton module does not enable you to call the instance methods directly:
Foo.test # => NoMethodError (private method `test' called for Foo:Class)
Foo.instance.test # => "hello"
一个单身的班级:

class Foo
end

# create two instances:
foo1 = Foo.new
foo2 = Foo.new

foo1 == foo2 # => false 
require 'singleton'
class Foo
  include Singleton

  def test
    "hello"
  end
end

# you can't create an instance:
foo = Foo.new # => NoMethodError (private method `new' called for Foo:Class)

# there is one global instance:
foo1 = Foo.instance
foo2 = Foo.instance
foo1 == foo2 # => true

# the Singleton module does not enable you to call the instance methods directly:
Foo.test # => NoMethodError (private method `test' called for Foo:Class)
Foo.instance.test # => "hello"

我不认为在很多情况下,单例类实际上是问题的最佳解决方案。

它们没有多少共同点。单例类只能实例化一次。在您的情况下,我可以创建任意数量的实例:
@browser1 | |=Browser.new@browser2 | |=Browser.new
啊,我现在明白你的意思了。谢谢你的评论。如果你想把评论作为答案,我会把它标记为已解决。我把事情搞糊涂了…仅供参考:
@browser
是一个实例变量,以
$
开头。谢谢提醒,我忘记了一些概念…:(@mickael:BTW,对于实现单例类的各种可能性,请看一看。我通常使用那篇文章中描述的
扩展self
技巧来创建单例类。通常
|124;=
用于记忆,但它真正做的是为变量设置一个值,除非该变量已经包含真实值@KimmoLehto当然可以,但我认为一个示例可能更有用,因为OP要求的是实际的差异,而不是实现细节。非常感谢这两个示例,非常清楚示例之间的差异。解释得非常好。我可以考虑使用单例的情况,例如,创建一个
@logger变量来捕获记录错误,但在我们的例子中,我们总是使用
@logger变量,因此最终结果似乎与使用不同的变量相似,这些变量实例化了同一个单例类,因此对于我们都知道在测试框架中使用什么的小团队,我无法如此清楚地看到好处。
require 'singleton'
class Foo
  include Singleton

  def test
    "hello"
  end
end

# you can't create an instance:
foo = Foo.new # => NoMethodError (private method `new' called for Foo:Class)

# there is one global instance:
foo1 = Foo.instance
foo2 = Foo.instance
foo1 == foo2 # => true

# the Singleton module does not enable you to call the instance methods directly:
Foo.test # => NoMethodError (private method `test' called for Foo:Class)
Foo.instance.test # => "hello"