k-tokitoh

2019-05-13

Rubyによるデザインパターン - singleton

[![Rubyによるデザインパターン](https://images-fe.ssl-images- amazon.com/images/I/41PNvUxHtgL.SL160.jpg)](http://www.amazon.co.jp/exec/obidos/ASIN/4894712857/hatena- blog-22/)

利用する場面

オブジェクトが複数のインスタンスを生成する必要がなく、そのオブジェクトを唯一存在させたい場合。

サンプル

まずはクラス変数に唯一のインスタンスをつくれなくする方法。

class Fuji
  attr_reader :height
  def initialize
    @height = 3776
  end

  @@instance = self.new

  def self.instance
    return @@instance
  end

  def erupt
    p "DOOOOOOOOOOOONNNNN!!!!!!!"
  end

  private_class_method :new
end

p Fuji.instance.height # => 3776
Fuji.instance.erupt # => "DOOOOOOOOOOOONNNNN!!!!!!!"

続いて、Ruby の組み込みモジュールを利用する方法。(構造は上と同じ。)

require 'singleton'

class Fuji
  include Singleton
  attr_reader :height

  def initialize
    @height = 3776
  end

  def erupt
    p "DOOOOOOOOOOOONNNNN!!!!!!!"
  end
end

p Fuji.instance.height # => 3776
Fuji.instance.erupt # => "DOOOOOOOOOOOONNNNN!!!!!!!"

インスタンス自体をつくらず、クラス自体を唯一のオブジェクトとして扱うパターン。

class Fuji
  @@height = 3776
  def self.height
    @@height
  end

  def self.erupt
    p "DOOOOOOOOOOOONNNNN!!!!!!!"
  end
end

p Fuji.height # => 3776
Fuji.erupt # => "DOOOOOOOOOOOONNNNN!!!!!!!"

最後に、module を唯一のオブジェクトとして扱うパターン。(module だとそもそもインスタンスができることを心配しなくてよい。)

module Fuji
  @@height = 3776
  def self.height
    @@height
  end

  def self.erupt
    p "DOOOOOOOOOOOONNNNN!!!!!!!"
  end
end

p Fuji.height # => 3776
Fuji.erupt # => "DOOOOOOOOOOOONNNNN!!!!!!!"

その他

クラス変数に getter と setter を持たせたい場合、自前で定義する必要がある。 ただし Rails では class_attribute などの組み込みメソッドが用意されている。

参考:Rails: クラスレベルの 3 つのアクセサを比較する(翻訳)