Design Pattern

Entries

Design Patter by PHP[8]: Mediator in javascript

Date
2007-06-01 (Fri)
Category
Design Pattern

だいぶ間が空いた第八回目は、16章の Mediator を Javascript でやってみようという番外編です。

(シーケンス図を入れる。)

また今回も、せっかく Javascript ですから Browser から実行できるようにしてみました。以下を試してみてください。

Mediator Pattern

コードはいつも通り、Subversion のレポジトリにあります。

http://svn.nydd.org/dpxphp/MediatorJS/

今回の気づき

  • Java でいう Interface を Javascript でどう実現したらいいかちょっと思いつかなかった。しかし結城さんの例では、Colleague と ConcreteColleague の関係など、Java のコンパイラによる型の強制、という意味以上にはとれないけれども。
  • setMediator のところで Event を初期化しているのは、そうしないと this.mediator がない、とエラーになるから。そういう意味では、mediator をコンストラクタの変数で渡せばいいのでは?という疑問が沸々と湧いてくるが…?
  • Javascript は相変わらず、Event Handler に於ける This の扱いが面倒だ。
  • このパターンだけだと、結局増える ConcreteColleague の単純化を助けてはくれないな…

Continue reading

Design Patter by PHP[7]: Builder

Date
2006-12-03 (Sun)
Category
Design Pattern

第七回目は Builder です。

Class Diagram: Builder Pattern

また今回は、Browser から実行できるようにしてみました。以下を試してみてください。

Builder Pattern

コードはいつも通り、Subversion のレポジトリにあります。

http://svn.nydd.org/dpxphp/Builder/

今回の気づき

  • 結城さんの本の中では、Director クラスのコンストラクタの第一引数の型として Builder クラスが指定してある。PHP でも version 5 から、タイプヒンティング(typehinting)と呼ばれる、code 表現上では似たようなことができるようになった。しかしこれはコード表現が似ているだけ。
  • Java では、継承する親の型を指定しておくことで、後に呼び出すことになる共通のメンバメソッドを強制することができるし、それが内部インターフェイスとしての役割を果たす。今回の Director.php でタイプヒンティングをすると、コンストラクタを呼び出す所で、Argument 1 passed to Director::__construct() must be an instance of Builder というエラーが起きる。つまりタイプヒンティングは型チェックをするだけなんですな(PHP は弱い型なので、当然なのか、な)。そういう意味では、Director クラスは、クラスではなく、インターフェイスにした方が、self explanatory だったかもしれない。
  • 追記 on March 2007: 嘘。Java の知識も曖昧です。今度書き直す。。
  • HTMLBuilder の中で、 DOM 関数を使用しているのだけれど、この DOM 関数は CLI 環境では存在しなかった。
    勘違い。この間 Mac OS X のセキュリティアップデートをしたから、一部のローカル設定が消去されて、デフォルト組み込みの PHP 4.4 がコマンドラインでは起動していたのだった。。
  • 暫く DOM 関数を使っていなかったので、勝手を忘れていてちょっと困った。というわけでいかにもう一度以下にまとめておきます。

PHP の DOM 関数の注意

動作確認に使用したのは、PHP Version 5.1.2 / libxml 2.6.16 のようです。

PHP の DOM 関数では、独立した (DOMDocument に append されていない) DOMElement には appendChild できない。

どういうことか。以下のコード参照。

<?php
$domdoc = new DOMDocument();
$html = new DOMElement('html'); $head = new DOMElement('head'); $title = new DOMElement('title', 'WTF');
$head->appendChild($title);
$domdoc->appendChild($html); $html->appendChild($head); ?>

上記コードは、動かない。実行すると 8行目で 'No Modification Allowed Error' というエラーが出る。理由はよくわかりませんが… しかし独立していなければ、DOMElement も appendChild できる、ということは、下のように実行順序を変えるだけでこのコードは動く。

<?php
$domdoc = new DOMDocument();
$html = new DOMElement('html'); $head = new DOMElement('head'); $title = new DOMElement('title', 'WTF');
$domdoc->appendChild($html); $html->appendChild($head); $head->appendChild($title); ?>

もうちょっと書き方を変えると、以下のようにも書ける。

<?php
$domdoc = new DOMDocument();
$html = new DOMElement('html'); $head = $html->appendChild( new DOMElement('head') ); $title = $head->appendChild( new DOMElement('title', 'WTF') ); ?>

最後のが一番シンプルな気もするけれど、場合によりけりでしょう。一番意味の通るものを使うべきだと思います。

Continue reading

Design Patter by PHP[6]: Prototype

Date
2006-11-26 (Sun)
Category
Design Pattern

第六回目は Prototype です。コードは毎回 Subversion のレポジトリ

http://svn.nydd.org/dpxphp/Prototype/

にあります。

今回から UML 図を書いてみることにしました。っていうか、全部本に書いてある通りですけれども。

Class Diagram: Prototype Pattern

今回の気づき

  • PHP の clone は、Java のようなメソッドではなく、new などと同じ、言語構造。しかし個別 class にて __clone() という特殊なメソッドを用意すれば、override 可能。
    オブジェクトのクローンが作成される際、PHP 5 は、そのオブジェクトのプロパティを 全てシャローコピーします。他の変数へのリファレンスを保持する全てのプロパティは、 リファレンスのままとなります。 __clone() メソッドが定義された場合、新規の作成されたオブジェクトの __clone() メソッドがコールされるため、この中で、プロパティに 必要な変更を行うことができます。
  • 上記引用ページに出てくる self というキーワード。どっかで読んだけどなんだっけ? static キーワードにあるように、static な変数にアクセスする this ということですな。予約語の一覧というページのユーザコメントに、
    The list also seems to be missing both "parent" and "self" as well.
    とある(しょーもな…)。
  • interface に abstract 宣言は必要ない、というより設定するとエラーが出る。

Design Patter by PHP[5]: Singleton

Date
2006-11-19 (Sun)
Category
Design Pattern

第五回目は Singleton です。コードは毎回 Subversion のレポジトリ

http://svn.nydd.org/dpxphp/Singleton/

にあります。

今回の気づき

  • Singleton は結構思考訓練になった気がする。Class があって、Instance があって、Nested な構造をうまく紐解く感じ。
  • 綴りミスとか言う下らないことで少し詰まった。。
    • 怪我の功名じゃないけれど、綴りミスで気がついたこと。PHP ってインスタンスに対して自由にメンバ変数を設定できる。参照: addmember.php
    • Method の追加はどうやってもできなさそう。
    • function 型は String に cast されて代入される。だから create_function の値は lambda_1 とかいう値に。
    • アクセス修飾子は設定できないだろうなぁ。というか試してすらいないし、やり方も思いつかん。
  • Triple の結果を確かめるのに、serialize を使ってみた。Serialize で帰ってくる string の仕様については Yahoo Developer Network: Using Serialized PHP with Yahoo! Web Servicesを参照。

Design Patter by PHP[4]: Factory Method

Date
2006-10-31 (Tue)
Category
Design Pattern | php

第四回目は Factory Method です。コードは毎回 Subversion のレポジトリ

http://svn.nydd.org/dpxphp/

にあります。

今回の気づき

  • PHP って packaging 機構はないのかなぁ。。PEAR にあるにはあるが、ちょとめんどい。そろそろ class auto load の仕組みをそろそろ覚えるべきかも。

実行結果は

$ php main.php
The card for Takashi will be made.
The card for John will be made.
The card for Carren will be made.
The card for Takashi will be used.
The card for John will be used.
The card for Carren will be used.

でした。

Design Patter by PHP[3]: Template Method

Date
2006-10-18 (Wed)
Category
Design Pattern | Tech | php

日々是鍛錬。

第三回目は Template Method です。コードは前回に引き続き、Subversion のレポジトリ

http://svn.nydd.org/dpxphp/

をどうぞ。

今回の気づき

  • 毎回思っていたけれど、PHP では名前空間の制約が厳しく、標準ライブラリに存在する関数と同じ名前の関数を定義できない。前2回分では、SPL で宣言されているクラス名と当たっていて、今回は標準関数の print だった。特に関数はなんとかしてもらいたい所ではある。だって内側から呼ぶのも $this つけなきゃ行けないわけだし、ambiguity はなさそうだけれども…
  • println ってなかったっけ??
  • 字数を数えるのにちょっと苦労した。以下 StringDisplay.php より
    $this->width = mb_strlen($this->str);
          if ( $this->width != strlen($this->str) ) {
             $this->width = $this->width * 2;
          }
    要するに、mb_strlen と strlen で数えてみて、一致してなかったらマルチバイト文字列と判断して、そうだったら、とりあえず2倍にしてある。ホントは private $is_mb とかつけて、printLine() を工夫すべきか、な。
    • 少し正確に話すと、unicode では(ASCII 互換以外の文字列、いわゆるダブルバイトと呼ばれているもの)1文字3byte消費しているの(だよね?)で、『あ』の1文字で strlen では 3 という返り値、mb_strlen では 1 という返り値を得る。ま〜正確ではあるけど、使いやすくはないのかな〜
    • 追記 on March 2007: Unicode 、と一緒くたに語っていますが、これは正確じゃない。例えば(日本語の wikipedia によればほとんど使われていないらしいが) UTF-1 は 8-bit (≒ 1byte) コード。ここで語ろうとしている UTF-8 はマルチバイトで可変長 ( 1〜4 byte ) 。『あ』が 3byte だったのは“たまたま”。この実装は間違いですな。

実行結果は

$ php main.php 
<<HHHHH>>
+-------------+
|Hello, World.|
|Hello, World.|
|Hello, World.|
|Hello, World.|
|Hello, World.|
+-------------+
+------------+
|こんにちは。|
|こんにちは。|
|こんにちは。|
|こんにちは。|
|こんにちは。|
+------------+

でした。

Design Patter by PHP[2]: Adapter

Date
2006-10-16 (Mon)
Category
Design Pattern | Tech | php

前回の イテレータ パターン からはだいぶ時間が空いてしまいました。本を友人に貸していたからなんですが、まぁ言い訳はこのくらいにして。

未だ Chpater 2: Adapter Pattern です。今回からは(昨日から運用開始した)Subversion を使ってレポジトリを公開〜。まだ非常に稚拙なコードですが、興味のある人は、

http://svn.nydd.org/dpxphp/

をどうぞ。

今回の気づき

  • Java の super() は PHP で parent:: となる。
    • PHP4 では class 名と同じ function がコンストラクタに、いわゆる Java と同じ形式だけだったのに、PHP5 から Object に __construct() という特殊関数ができて、誰が使うんだろーなー、と正直思っていたけれど、なるほど確かに parent::__construct() を呼ぶのに、統一的かつ合理的にするには __construct() を使うべきだと思いました。ちなみにマニュアルにはこう書いてあります。
      For backwards compatibility, if PHP 5 cannot find a __construct() function for a given class, it will search for the old-style constructor function, by the name of the class. Effectively, it means that the only case that would have compatibility issues is if the class had a method named __construct() which was used for different semantics.
      実際実験してみましたが、__construct() を class 宣言の中に含めなくても parent::__construct() で呼び出すことができています。
  • PHP とは関係なく、svnX の使い勝手の問題なんですが、Working Copies ウィンドウから開けるところで、Update ボタンを押すと、"Are you sure you want to update this working copy to the latest revision?" って聞いてくれるのだけれども、Yes を押すと、どれが変わるとかは言ってくれないで、黙ってアップデートされてるのがすこし気になった。

Iterator Pattern

Date
2006-07-16 (Sun)
Category
Design Pattern | php

もう今更ですが、PHP 再入門というか、Object 指向再入門してみようと思い立ちました。だいぶ前に買って一度 java でやったのですが、PHP でやってやろうと。

目次通りにやって行くつもりなので、初回はやや簡単ですが、Iterator です。

最初にちょっとだけ詰まったのが、関数の戻り値をどうやって参照で渡す方法でした。もちろん本書では Java でやってるので、値を渡す時は参照が基本だけれども、PHP はそうではないので明示してやる必要があります。マニュアル以下のページに書いてあります。

リファレンスを返す

簡単にまとめると

  • 変数への参照での代入
    $copy =& $originalObject
  • 関数の引数を参照で渡すことを明示
    function foo(&$var)
    {
    	$var++;
    }
  • 関数の戻り値を参照で返すことを明示
    function &foo( $param )
    {
    	/* ... コード ... */
    	return $bar;
    }

でした。

あと Iterator.php のコード中にでてくるインターフェイス名が YIterator となっているのは、PHP が内部的に Iterator というクラスを定義しているからです。マニュアルを見て発見したですが、CXLV. Standard PHP Library (SPL) 関数 というクラスライブラリが提供されているのですね…スゴいそろってるじゃん。。

SPL-StandardPHPLibrary Class List

foreach を使った時に、iterate されないクラスメンバとかはこれらを使うと設定できるみたいでした。今回のデザインパターン入門が終わったら見てみたいと思います。

Continue reading

Return to Page Top