Help us understand the problem. What is going on with this article?

Singleton パターン

More than 5 years have passed since last update.

物議を醸し出しがちなパターン

どんなパターン?

アプリの中で、そのclassのインスタンスの存在が1つしか許されない時に使用するパターン

Singleton パターンを用いると、そのクラスのインスタンスが1つしか生成されないことを保証することができる。 ロケールやLook&Feelなど、絶対にアプリケーション全体で統一しなければならない仕組みの実装に使用される

どんな時に使うの?

例えば、設定ファイルの内容のコンテナ。アプリ上で1回だけ読めば良いやつとか

ruby だと、singleton モジュールを使えばOK

singleton.rb
require 'singleton'

# 設定ファイルの情報を格納する class
#
class Setting
  include Singleton
  def initialize
    @settings = YAML.load_file("settings.yml")
  end

  def [](key)
    @settings(key)
  end
end

# シングルトン は、#instance で、インスタンスを呼び出す
p Setting.instance.object_id # 70341972008800
p Setting.instance.object_id # 70341972008800

Setting.instance['name']

# private method `new' called for SingletonClass:Class (NoMethodError)

クラス変数を使っても同様の実装は可能

singleton.rb
require 'singleton'

# 設定ファイルの情報を格納する class
#
class Setting
  def self.[](key)
    settings(key)
  end

  def self.settings
    @@settings ||= YAML.load_file("settings.yml")
  end
end

Setting['name']

どっちが良いかはよくわかってないけど、個人的には明示的にシングルトンであることが判るから、
Singleton を Mix-in する方が良いと思う

Singleton の問題点

いろいろある

グローバル変数の代わりになってしまう

何かしら状態を持つ Singleton の場合、その状態が色々な所で勝手に変更されてしまうとカオス

→ 状態が変更されるようなクラスは、Singleton にしない方が良い

テストで順序依存が発生しやすい

何かしら状態を持つ Singleton の場合、
次のテストでも、その状態が維持されるため

before で、クラスをリセットする必要がある

コードが密結合になる

Setting.instance を呼んだ class は、Setting class と密結合になる

  • 密結合はテストの敵
  • Setting ではない class を使うように変更になった時に、全てのコードを置換する必要が出る

→ 取りに行くのではなく、コンストラクタの引数で、貰うようにする
→ シングルトンにするのは良いけど、色んな class で好き勝手に instance を呼ばないようにする

で、シングルトンは使って良いものなの?

個人的には、上記の意見を意識した上で使うべき理由が見いだせないので、使うことには消極的
ただ、色々な所でコンストラクタの引数で必要なインスタンスを渡すというのもちょっと違和感があるよね...

迷ってます

参考

kasei-san
小林の中の人 長文はblogに。QiitaにはちょっとしたTIPSを
http://kasei-san.hatenablog.com/
lclco
業界最大手高速バス料金比較サイト「バス比較なび」やLCCなど飛行機との比較ができる「格安移動」を運営
https://www.lclco.com/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away