2021年3月17日水曜日

Ruby でシングルトンなクラスを作成する方法

概要

Singleton は 1 つのクラスから 1 つのオブジェクトのみを生成させることができる機能です
システム全体で共有して使うようなクラスが必要な場合に使うパターンが多いです

環境

  • Ruby 3.0.0p0

サンプルコード

  • vim app.rb
require 'singleton'

class TestSingleton
  include Singleton

  attr_accessor :counter

  def initialize
    @counter = 0
  end
end

ts1 = TestSingleton.instance
ts1.counter += 1
p ts1.counter
p ts1.object_id

ts2 = TestSingleton.instance
ts2.counter += 1
p ts2.counter
p ts2.object_id

TestSingleton.new # => NoMethodError

同一の object_id が返ってくることと counter の値が共有されていることが確認できると思います
なお Singleton にしたクラスでは new ができなくなります

new もできるようにする

method_missing を使います

require 'singleton'

class TestSingleton
  include Singleton

  attr_accessor :counter

  def initialize
    @counter = 0
  end

  def self.method_missing(method, *args, &block)
    TestSingleton.instance
  end
end

ts1 = TestSingleton.instance
ts1.counter += 1
p ts1.counter
p ts1.object_id

ts2 = TestSingleton.instance
ts2.counter += 1
p ts2.counter
p ts2.object_id

ts3 = TestSingleton.new # => NoMethodError
ts3.counter += 1
p ts3.counter
p ts3.object_id

デメリット

コードが密結合になりやすいのでユニットテストが書きづらくなるのが個人的には一番のデメリットかなと思います
DI などによる回避方法が簡単な方法かなと思います

参考サイト

0 件のコメント:

コメントを投稿