在Ruby中编写单例模式的正确方法是什么?

我正在尝试用Ruby编写最安全的单例。 我是这种语言的新手,它非常有弹性,我没有强烈的感觉,我的单例类将成功创建一个实例。 作为奖励,我希望该对象只有在真正使用时才会被实例化。

# require singleton lib require 'singleton' class AppConfig # mixin the singleton module include Singleton # do the actual app configuration def load_config(file) # do your work here puts "Application configuration file was loaded from file: #{file}" end end conf1 = AppConfig.instance conf1.load_config "/home/khelll/conf.yml" #=>Application configuration file was loaded from file: /home/khelll/conf.yml conf2 = AppConfig.instance puts conf1 == conf2 #=>true # notice the following 2 lines won't work AppConfig.new rescue(puts $!) #=> new method is private # dup won't work conf1.dup rescue(puts $!) #=>private method `new' called for AppConfig:Class #=>can't dup instance of singleton AppConfig 

那么当你在课堂中包含单例模块时,ruby会怎么做?

  1. 它使new方法变为私有,因此您无法使用它。
  2. 它添加了一个名为instance的类方法,该方法仅实例化该类的一个实例。

因此,要使用ruby singleton模块,您需要两件事:

  1. 需要lib singleton然后将其包含在所需的类中。
  2. 使用instance方法获取所需的实例。

如果你想创建一个单例,为什么还要创建一个类呢? 只需创建一个对象,然后将方法和实例变量添加到所需的对象中。

 >> MySingleton = Object.new => # >> MySingleton.instance_eval do ?> @count = 0 >> def next >> @count += 1 >> end >> end => nil >> MySingleton.next => 1 >> MySingleton.next => 2 >> MySingleton.next => 3 

人们实现此模式的一种更标准的方法是使用Module作为单例对象(而不是更通用的Object ):

 >> module OtherSingleton >> @index = -1 >> @colors = %w{ red green blue } >> def self.change >> @colors[(@index += 1) % @colors.size] >> end >> end => nil >> OtherSingleton.change => "red" >> OtherSingleton.change => "green" >> OtherSingleton.change => "blue" >> OtherSingleton.change => "red" 

如果您希望单个对象从某个类inheritance,只需将其作为该类的实例即可。 要从mixininheritance,只需使用#extend 。 如果你想要一个单例对象,ruby使它变得非常容易,而且与其他语言不同,它不必在类中定义。

特设单身人士(我的第一个例子)到处都是,涵盖了我遇到的大多数情况。 模块技巧通常涵盖其余部分(当我想要一些更正式的东西时)。

Ruby代码应该(imho)使用duck typing(通过#respond_to? )而不是显式检查对象的类,所以我通常不关心我的单例对象类的唯一性,因为它不是它的类使其独特,但我之后添加的一切。

 require 'singleton' class Klass include Singleton # ... end 

有关说明,请参阅Ruby Standard Library Singleton类文档 。