2009-09-27 10 views
25

私はRubyで最も安全なシングルトンを書くつもりです。私は言語に慣れていないので、弾力性があり、私のシングルトンクラスが1つのインスタンスを作成するのに成功するという強い感覚はありません。ボーナスとして、実際に使用されている場合にのみオブジェクトがインスタンス化されるようにしたいと思います。Rubyでシングルトンパターンを作成する正しい方法は何ですか?

答えて

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 

シングルトンモジュールをクラスに含めると、ルビは何をしますか?

  1. newメソッドはプライベートなので、使用できません。
  2. クラスのインスタンスを1つしかインスタンス化しないインスタンスと呼ばれるクラスメソッドを追加します。

だから、ルビーシングルトンモジュールを使用するには、二つのことを必要とする:

  1. は、所望のクラスの中にそれを含めるのlib singletonを必要としています。
  2. instanceメソッドを使用して、必要なインスタンスを取得します。
16

シングルトンを作成する場合、クラスを作成するのはなぜですか?オブジェクトを作成し、必要なメソッドとインスタンス変数を追加します。あなたのシングルトンオブジェクトを継承したい場合

>> 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" 

:人々は、このパターンを実装することを

>> 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 

より標準的な方法は、(というより一般的なObjectより)シングルトンオブジェクトとしてModuleを使用することですいくつかのクラスは、単にそれをそのクラスのインスタンスにします。 mixinから継承するには、#extendを使用してください。シングルトンオブジェクトが必要な場合、Rubyは本当に簡単ですし、他の言語とは異なり、クラスで定義する必要はありません。

アドホックシングルトン(私の最初の例)は、すべての場所にあり、私が遭遇した大部分のケースをカバーしています。モジュールのトリックは通常、残りの部分をカバーしています(私はもう少し正式なものが必要なとき)。

Rubyコードでは、明示的にオブジェクトのクラスをチェックするのではなく、ダックの型指定(#respond_to?経由)を使用する必要があります。したがって、私は通常、自分のクラスの一意性を気にしません。ユニークですが、後に追加したものすべて。

+6

+1は、シングルトンが本当に必要でないことを指摘しています。パターンを忠実にコピーすることなく意図を実装することができます。 –

+0

私は、この点について懸命に考えてきました。なぜなら、それは、ルービックコアにおけるシングルトンモジュールの存在自体に疑問をもたらすからです。クラスとインスタンスメソッドの両方が必要な場合、2)複雑な初期化をしている場合は、モジュールメソッドを何らかの方法で明示的に起動させることなく遅延的に実行したい場合は、Singleton mixinのクラスの潜在的な有用性は2つに分かります彼らが初めてアクセスされたとき。他の誰かが実際のシングルトンモジュールの利点を持っていますか? – gtd

関連する問題