[iOS 8] Swiftでデザインパターン No.1 Singleton

はじめに

これから数回に渡り、Swiftでデザインパターンを実装していきます。

Swiftはとてもシンプルに記述ができるため、工夫次第でコードを短くできますが、
私はあえてクラス図通りに書いてみようと思います。

そうすることで、できること/できないことが見えてきて、Swiftについて深く学べるのではないかと考えました。
よって、ここでの目的はデザインパターンの習得ではなく、Swiftについて理解を深めることとします。

余裕があれば、Swiftならではの記述もしてみよう思いますのでお楽しみに。

Singleton

Singletonとは

英単語Singletonには以下のような意味があります。

  • 一枚札
  • 単独で活動する人(物)

Singletonパターンは、そのクラスのインスタンスが1つしか生成されないことを保証することができるデザインパターンです。

クラス図

class_diagram_singleton

ポイント

  1. 同じ型のインスタンスがprivateなクラス変数として定義されている
  2. コンストラクタの可視性がprivateである
  3. 同じ型のインスタンスを返すgetInstance()がクラス関数として定義されている

サンプルコード

private let singleton = Singleton()

class Singleton {

    private init() {}

    class func getInstance() -> Singleton {
        return singleton
    }
}

解説

private let singleton = Singleton()

この行ではポイント1の記述を表現しています。

同じ型のインスタンスがprivateなクラス変数として定義されている

が、いきなりSwiftでできること/できないことが同時に出てきました。

  • できること
    • グローバル変数/定数を定義するときにメソッドを使って初期化できる
  • できないこと
    • staticなクラス変数/定数を定義することはできない

よってここでは「同じ型のインスタンス」はグローバル定数として定義しています。

なおこのコードでは、定数はアクセス時に初めて初期化され(遅延初期化)、dispatch_onceが走ります。
Appleによると、dispatch_onceをクールに使う方法は、「イニシャライザーを持つグローバル変数を宣言して、private修飾子をつけろ」だそうです。詳しくはこちら


private init() {}

この行ではポイント2の記述を表現しています。

コンストラクタの可視性がprivateである

initメソッドをprivateにしているだけです。
この記述によって、このクラスの外から以下のようにインスタンスを生成することはできなくなります。

Singleton()


ここではポイント3の記述を表現しています。

同じ型のインスタンスを返すgetInstance()がクラス関数として定義されている

class func getInstance() -> Singleton {
    return singleton
}

getInstanceメソッドで、インスタンスを返しています。
initメソッドがprivateなため、このクラスのインスタンスを取得するためにはこのメソッドを呼ぶ必要があります。

まとめ

  • グローバル変数/定数を定義するときにメソッドを使って初期化できる
  • dispatch_once相当のことはクールに記述することができる
  • staticなクラス変数/定数を定義することはできない

こんなところです。

おまけ

Swiftならではの書き方

class Singleton {
    class var sharedInstance :Singleton {
        struct Static {
            static let instance = Singleton()
        }
        return Static.instance
    }
}

クラスとは違い、構造体はstaticな変数/定数を定義することができます。

よって、この書き方がベストではないかとこちらで話題になっています。