我正在尝试用Ruby编写最安全的单例。我对这种语言很陌生,这种语言很有弹性,我没有强烈的感觉,我的单例类只能创建一个实例。作为奖励,我希望该对象只有在真正使用时才会被实例化。
答案 0 :(得分:43)
# 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会怎么做?
new
方法变为私有,因此您无法使用它。因此,要使用ruby singleton模块,您需要做两件事:
singleton
,然后将其包含在所需的类中。instance
方法获取所需的实例。答案 1 :(得分:17)
如果你想创建一个单例,为什么还要创建一个类呢?只需创建一个对象,然后将方法和实例变量添加到所需的对象中。
>> MySingleton = Object.new
=> #<Object:0x100390318>
>> 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"
如果您希望单个对象从某个类继承,只需将其作为该类的实例即可。要从mixin继承,只需使用#extend
。如果你想要一个单例对象,ruby使它变得非常容易,而且与其他语言不同,它不必在类中定义。
Ad-hoc单身人士(我的第一个例子)到处都是,涵盖了我遇到的大多数情况。模块技巧通常涵盖其余部分(当我想要更正式的东西时)。
Ruby代码应该(imho)使用duck typing(通过#respond_to?
)而不是显式检查对象的类,所以我通常不关心我的单例对象类的唯一性,因为它不是它的类这使得它独一无二,但我之后添加了所有内容。
答案 2 :(得分:8)
require 'singleton'
class Klass
include Singleton
# ...
end