銀行員からのRailsエンジニア

銀行員からのRailsエンジニア

銀行員から転身したサービス作りが大好きなRailsエンジニアのブログです。個人で開発したサービスをいくつか運営しており、今も新しいサービスを開発しています。転職して日々感じていること、個人開発サービス運営のことなどを等身大で書いていきます。

【Rubyによるデザインパターンまとめ10】シングルトンパターン

コードの品質向上のため、Rubyデザインパターンを解説した名著である Rubyによるデザインパターン で紹介されているデザインパターンを1つずつまとめており、今回が第10弾です。(毎週1つが目標です!)

前回の記事(デコレータパターンのまとめ)はこちらです。
【Rubyによるデザインパターンまとめ9】デコレータパターン - 銀行員からのRailsエンジニア

この本で紹介されているサンプルコードそのままではなく、オリジナルのコードで説明しています。

今回は シングルトン(Singleton)パターン についてまとめました。

f:id:ysk_pro:20200112100112p:plain

シングルトンパターンとは

ただ1つのインスタンスしか持てないクラスを作り、その1つのインスタンスへのアクセスをグローバルに提供するパターンです。

Singletonという単語は、トランプの一枚札(唯一存在するカード)という意味で、インスタンスが1つしか存在しないことを表しています。

文章の説明よりも実際のコードを見た方が分かりやすいと思うので、以下のサンプルコードをご覧ください。

サンプルコード

ジムでダンベルを使いたいとき、他の人に使われているとテンションが下がりますよね。。

ということで、ダンベルの貸し借りを管理する簡単なプログラムを考えてみましょう。

class Dumbbell
  def initialize
    @usable = true # ダンベルを使用できるかどうか
  end

  def borrow
    if @usable
      @usable = false
      puts 'ダンベルを借りたよ。筋トレファイト!'
    else
      puts 'ダンベルはレンタル中だよ。他の筋トレをしよう!'
    end
  end

  def return
    @usable = true
    puts 'ダンベルを返却したよ。お疲れさま!'
  end

  @@instance = Dumbbell.new # クラス変数

  def self.instance
    @@instance
  end

  private_class_method :new
end

インスタンスが1つしか存在しないことを利用して、唯一のインスタンスインスタンス変数(@usable)でダンベルを使用できるかを管理しています。

以下のように実行します。

Dumbbell.instance.borrow
Dumbbell.instance.borrow
Dumbbell.instance.return

Dumbell.instanceで、唯一存在するインスタンスを呼び出しています。

ダンベルを借りたよ。筋トレファイト!
ダンベルはレンタル中だよ。他の筋トレをしよう!
ダンベルを返却したよ。お疲れさま!

newメソッドをプライベートメソッドにすることで、外部からDumbbell.newインスタンスを作ることができなくなり、Dumbbelクラスがインスタンスをただ1つしか持たないことを保証しています。

以下のように実行するとエラーとなります。

Dumbbell.new.borrow


また、RubyにはSingletonモジュールが用意されており、Singletonモジュールを使用するとシングルトンパターンがシンプルに実装できます。

先ほどのコードをSingletonモジュールを使ってリファクタリングしてみましょう。

require 'singleton'

class Dumbbell
  include Singleton

  def initialize
    @usable = true # ダンベルを使用できるかどうか
  end

  def borrow
    if @usable
      @usable = false
      puts 'ダンベルを借りたよ。筋トレファイト!'
    else
      puts 'ダンベルはレンタル中だよ。他の筋トレをしよう!'
    end
  end

  def return
    @usable = true
    puts 'ダンベルを返却したよ。お疲れさま!'
  end
end

Singletonモジュールをincludeすると、先に書いたコードと同様の以下3点を行ってくれます。

  • インスタンスを作成し、それをクラス変数に格納すること
  • instance というクラスメソッドを作ること
  • newメソッドをプライベート化すること

全て(実行の仕方・結果・newを呼び出すとエラーとなること)先ほどと同じ結果になります。

シンプルに実装でき、実装漏れもなくなるので、実際にシングルトンパターンを使うときはSingletonモジュールを利用するのが良さそうです。

おわりに

ここまで読んでいただきありがとうございます。

Rubyによるデザインパターン の中では、Loggerクラスを題材にしたリアルなサンプルコードの説明や、シングルトンパターンを使う際の注意点などが記載されていて分かりやすかったので、ご興味ある方は是非合わせてご覧ください。

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

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

次回は、ファクトリ(Factory)メソッドパターンをまとめます。

来週も頑張ります!

(追記)
ファクトリメソッドパターンについてまとめました!
是非合わせてご覧ください。
ysk-pro.hatenablog.com