第11回 Net_UserAgent_Mobile クラス - 携帯端末情報取得ライブラリ (2) - PEAR講座

PHPセキュリティ

くまっち先生のPEAR講座

Lecutures on PHP

第11回 Net_UserAgent_Mobile クラス - 携帯端末情報取得ライブラリ (2) (その1)

 このエントリーをはてなブックマークに追加

デザインパターン

くまっち先生

デザインパターンとは、ソフトウェアの開発において再利用性を目的とした設計手法のことをいいます。幾度にも渡って様々なソフトウェアを開発するために行ってきたプログラミングを経て、ある問題にはこの解決法をといった具合に情報をまとめていった結果、いくつかの様式にまとめられ作られたもの、それがデザインパターンです。

このデザインパターンを知っている状況でプログラミングを行うと、とある処理や事柄を実現するためにどのようなプログラムの構成(プログラム設計)を組み立てれば良いかという道筋を、過去に登場した似たようなケースで用いられた解決策をそのまま適応することができるため、比較的スムーズに具体的なコードを記述することができ、かつ破綻しにくいプログラムを作り上げることができるというメリットがあります。

いわゆる、ある状況(シチュエーション)に対しての「定石」というのが分かりやすいかもしれません。すなわち、目の前におかれた問題に対しての最善の一手、セオリー、良くある解決策といえるものです。もちろん本来の定石のとおり、囲碁で定石通りに石を打ったとしても負けてしまうケースもありますし、そもそも状況に沿わないケースでは全く機能しないことにもなります。

もっと簡単にいうと、先人の知恵が盛り込まれている「プログラム指南書」とでも言えるでしょうか。ケーススタディに則った、良いとこ取りのできるHowTo本というわけです。

シングルトン・パターン

前回の講座ではNet_UserAgent_Mobileの使用例としていくつかのコードを紹介しました。このライブラリを利用する際に、クラスオブジェクトを以下のリスト1のように作成していました。

    リスト1Net_UserAgent_Mobileのオブジェクトを作成

    
require_once 'Net/UserAgent/Mobile.php';
    
$userAgent Net_UserAgent_Mobile::singleton();

通常は $userAgent = new Net_UserAgent_Mobile(); とでもするところですが、singletonというスタティックメソッドを使用して作成しています。
これこそ、デザインパターンの1つである「シングルトン・パターン」と呼ばれる手法による利用方法となります。

例えば、とある外部データを読み込む処理を行い、その内容に沿ったデータ構造を持つオブジェクトを作成するようなクラスがあるとします。外部データとは、ファイルやデータベース、あるいはリモートとの通信により得られるものなど様々なケースがあるでしょう。
このクラスを使いまわすことで何度かオブジェクトを作成する場合、そのたびに「new」を行い毎度外部データを読み込み構築する処理を実施していては、外部データの容量にもよりますが負荷が生じてしまいますし、パフォーマンスも低下することになります。

こういった無駄な処理を行わないことを目的として、オブジェクト生成を制限するための手法というものがシングルトン・パターンです。

具体的には、はじめにオブジェクトを生成した後、オブジェクトを再取得する際には同一のオブジェクト、すなわち最初に生成したオブジェクトを繰り返し利用することで、オブジェクト作成のための処理を省略することを実現します。

オブジェクト生成のための処理が行われない、すなわち「コンストラクタ処理」が2度目以降行われないことになりますので、前述のとおりパフォーマンス低下を防ぎたい場合や、必ず同一のオブジェクトを参照したいケースなどで用いられるテクニックです。

PHP で実現するシングルトン・パターン

リスト2は、シングルトン・パターンを実現したPHPコード例です。

    リスト2シングルトン・パターンのコード例

    
class ExampleClass
    
{
        function 
ExampleClass()
        {
            
sleep(1);
            
$this->name 'Example';
        }
    
        function &
singleton()
        {
             static 
$instance;
             if (!isset(
$instance)) {
                 
$instance = new ExampleClass();
             }
    
             return 
$instance;
        }
    }

くまっち先生

ここでは、オブジェクトを生成するタイミングで実施されるコンストラクト部の処理の例として、プロパティ値nameに 'Example' という文字列をセットしているのとあわせて、sleep関数を用いて1秒ほどのラグを生じさせています。

一方シングルトン・パターンとしてのコードは、singletonメソッドがメインとなります。
このメソッド内では$instanceという静的変数(*1)を準備し、この変数にクラスオブジェクトを割り当てるようにします。静的変数は、このメソッドの実行終了後も値を継続して保持し続けますので、再びsingletonメソッドを実行した場合、$instance内にはクラスオブジェクトを参照することが可能となります。値が格納されている2度目以降は、その$instance内のクラスオブジェクトをそのまま返すようにします。

このクラスに対し、以下のリスト3およびリスト4のそれぞれのコードをもって実行してみましょう。それぞれのコードにて、オブジェクトを生成した後にnameプロパティの値を出力しているという処理を2度続けて実施しています。

    リスト3シングルトンを使用せずにオブジェクトの生成・利用

    $exampleClass1 
= new ExampleClass();
    print 
$exampleClass1->name;
    
    
$exampleClass2 = new ExampleClass();
    print 
$exampleClass2->name;
    リスト4シングルトンを使用したオブジェクト生成・利用

    $exampleClass1 
ExampleClass::singleton();
    print 
$exampleClass1->name;
    
    
$exampleClass2 ExampleClass::singleton();
    print 
$exampleClass2->name;

リスト3のように new を使用してオブジェクトを生成する場合、生成時の度にsleep関数が実行され、1秒の実行遅延が発生することになります。
一方リスト4のようにシングルトンを使用してオブジェクトの生成を行う場合、最初のオブジェクト生成時にはsleep関数による実行遅延が発生しますが、2回目の生成時では実行遅延が発生せず即座に出力が行われます。
これは前述のとおり、オブジェクト生成を制限を目的として、2度目以降同一クラスのオブジェクトを生成する場合は、初回に作成したオブジェクトと同じものをそのまま返すようsingletonメソッド内で処理しているためです。

この実験コードでは1つのスクリプト内で同じクラスオブジェクトを続けて使用していますのでこのような利用方法をとることはありませんが、複数のスクリプトにまたがって数回オブジェクトを使用する場合に有効な利用方法となるでしょう。

----
*1) http://www.php.net/manual/ja/language.variables.scope.php#language.variables.scope.static

  



Pick Up Q&A

Q
動的なURLを静的に見せる方法
 このエントリーをはてなブックマークに追加 
A
普通に考えて、mod_rewrite でしょうね。 http://www.nishishi.com/blog/2006/01/mod_rewrite_url.html...

>>続きを読む

GETのままでは検索エンジンのロボットが拾ってくれなかったためにSEO対策として有効だと言われていますね。

▲解説者:岡本(アシアル株式会社 教育コーディネーター兼 システムエンジニア)