【コラム】
前回の予告通り、今回からデザインパターンをObjective-Cで実装してみる。
取り上げるパターンの順番だが、テキストとして使用する「オブジェクト指向における再利用のためのデザインパターン」(以下GoF本)とは少し変更する。まず生成に関するパターンから始めるのは同じだが、その中のSingletonを最初に取り上げよう。
Singletonは、インスタンスを1つしか生成しないクラスのためのデザインパターンだ。主な用途としては、ファイルマネージャや、ウィンドウマネージャなど、対象がただ1つしかないものが挙げられる。
Singletonクラスのインスタンスを取得する場合、通常のalloc、initといったメソッド(C++でのnewに相当)は、使わない。その代わりに、インスタンス取得のためのメソッドを提供することになる。作成された、ただ一つのインスタンスは、Singletonクラスで管理される。
さて、このようなパターンをObjective-Cで実装してみよう。まず、インスタンス取得のためのメソッドは、クラスメソッドを使う。次に、作成したインスタンスだが、本来ならクラス変数として管理したいところだが、Objective-Cにはクラス変数はない。そこでよく使われるのが、クラスの実装ファイルにstatic変数を宣言する方法だ。C言語で使われる単純な方法だが、機能としては十分だ。
Singletonという名前のクラスを定義しよう。インスタンスを得るために、instanceという名前のクラスメソッドを持つ。
実装は次のようになる。instanceメソッドの中でstaticのSingleton変数を宣言し、最初に呼び出されときにだけ、インスタンスを作成する。
実際に使うときは、次のようなコードになるだろう。
これで、ただ1つのSingletonインスタンスを使い回すことができる。基本的には、こういうスタイルになると思う。もう少し、突っ込んだ議論をしてみよう。
List 2では、最初にinstanceメソッドを呼び出したときに、インスタンスを作成した。このタイミングでの作成は、複数スレッドからこのメソッドが呼ばれる場合、問題が起こることがある。インスタンス作成のチェックを、_insntanceがnilかどうかで行っているので、スレッドの動作によっては、2つのインスタンスが作成されてしまう恐れがあるのだ。
これを避けるには、スレッドのロックを行うようにすればいい。Objective-Cではスレッド同期のための文法は提供されていないので、Cocoaやpthreadなどのライブラリを使うことになるだろう。
それ以外に、インスタンス作成のタイミングをもっと早めるという方法もある。例えば、クラスがランタイムに読み込まれるときに呼ばれる、loadメソッドを使えばいい。List 2を次のように変更することもできる。
この場合、instanceメソッドを呼び出したときには、すでにインスタンスは作成されていることになる。ただし、この実装にすると、次で説明するサブクラスへの対処が難しくなる。
先ほどのSingletonクラスを、NewSingletonというサブクラスで拡張することを考えてみよう。このとき、インスタンスは、SingletonかNewSingletonのどちらか1つだけを作るものとする。さて、どうすればよいか。
問題は、instanceメソッドが呼ばれたときに、どちらのクラスから呼ばれたのか? という点にある。Singletonクラスから呼ばれたののならばSingletonのインスタンスを作ればいいし、NewSingletonクラスならばそのインスタンスだ。
Objective-Cでは、クラスオブジェクトを使うことで解決できる。instanceはクラスメソッドなので、その内部ではself変数はクラスオブジェクトになる。これを使って、インスタンスを作成すればいい。
List 2を次のように変更しよう。
[Singleton alloc]としていたところを、[self alloc]と変更した。このようにすれば、[Singleton instance]を呼んだときはSingletonのインスタンスが作成され、[NewSingleton insntace]ならばNewSingletonのインスタンスになる。
GoF本では、インスタンスを作り分けるために、環境変数に名前を設定して、そこから判別する方法が紹介されている。
この方法では、作成するインスタンスの名前をあらかじめ設定しておく必要がある。Objective-Cでは、クラスメソッドからクラスのランタイム情報にアクセスできるので、追加の情報がなくともサブクラス化に対応できることが分かると思う。
次回は、Cocoaフレームワークの中に見られるSingletonパターンを紹介しよう。
【コラム】ライトニングJava 第64回 Servletプログラミング(4) - データスコープ、HTTPリクエスト/レスポンスヘッダ
【コラム】ライトニングJava 第63回 Servletプログラミング(3) - Webアプリケーションの初期値、サーブレットの初期値
| トマトを食べれば痩せられる!? -京大ら、新発見の成分で肥満改善効果を実証 [21:00 2/10] |
| JAXA、液体シリコン中に残存する共有結合を観察 -大口径ウェハの実現に期待 [20:11 2/10] |
| NEDOなど、熱膨張が小さな樹脂複合材料ペレットの量産化に成功 [19:22 2/10] |
| 理研、一般顕微鏡を蛍光顕微鏡に強化できるアダプタを試作して性能を実証 [19:15 2/10] |
| 天の川のブラックホールが小惑星を飲み込んでいる - NASAが発表 [18:08 2/10] |
|
【レポート】「appliko」がオススメAndroidアプリを紹介!! - 1月31日~2月8日のAndroidアプリランキング [01:30 2/11] 携帯 |
|
【レポート】人気の無料/有料アプリを毎週紹介 - 1月31日~2月8日のAndroidアプリランキング [01:00 2/11] 携帯 |
|
渡部篤郎主演でドラマ化!地元新聞社が伝え続けた東日本大震災の物語 [00:08 2/11] キャリア |
|
沖縄発ヒーロー革命!「琉神マブヤー」が海を越えハワイを目指す! [00:08 2/11] キャリア |
|
中国四川省、パンダの保護と生態研究の最新情報とは? [00:08 2/11] キャリア |