|
オブジェクト指向についてはまだまだ勉強中ですが、「PHPでGoFのデザインパターンを実装したら、どんな感じになるんだろ?」と思ってしまったので、ちょっとずつやってみることにしました。
間違いやご意見がありましたら、遠慮なくツッコミを入れてくださいm(_"_)m
今回は、Template Methodパターンで「親クラスで処理の枠決めを行い、サブクラスで具体的な実装を行う」パターンです(以下のクラス図を参照)。
クラス同士の関係はかなり単純で、抽象クラスとそのサブクラスだけで構成されます。今回のサンプルは、練習問題にも出てきそうな
- リソースの取得
- データの取得
- データの表示
- リソースの解放
というもので、お決まりのファイル入力とDB連携をやっています。上のクラス図との関係は、以下のようになります。
- AbstractClass => Template
- ConcreteClass => DbDisplay/FileDisplay
以下がサンプルコードです。
●TemplateMethod.php
<?php
class Template
{
function open()
{
}
function get()
{
}
function show()
{
}
function close()
{
}
function process()
{
$this->open();
$this->get();
$this->show();
$this->close();
}
}
class DbDisplay extends Template
{
var $conn_;
var $stmt_;
var $data_;
var $rows_;
function open()
{
$this->conn_ = OCILogon("scott", "tiger", "orcl");
}
function get()
{
$this->stmt_ = OCIParse($this->conn_, "SELECT * FROM emp");
OCIExecute($this->stmt_);
$this->rows_ = OCIFetchStatement($this->stmt_, $this->data_);
}
function show()
{
echo "<table border=\"1\">";
echo "<tr>";
while (list( $key, $val ) = each( $this->data_ ) ) {
echo "<th>$key</th>";
}
echo "</tr>";
for ( $i = 0; $i < $this->rows_; $i++ ) {
reset($this->data_);
echo "<tr>";
while ( $column = each($this->data_) ) {
$data = $column['value'];
echo "<td>$data[$i]</td>";
}
echo "</tr>";
}
echo "</table>";
}
function close()
{
OCIFreeStatement($this->stmt_);
OCILogOff($this->conn_);
}
}
class FileDisplay extends Template
{
var $fp_;
var $buf_;
function open()
{
$this->fp_ = fopen(__FILE__, "r");
}
function get()
{
while (!feof($this->fp_)) {
$this->buf_ .= fgets($this->fp_, 4096);
}
}
function show()
{
highlight_string($this->buf_);
}
function close()
{
fclose($this->fp_);
}
}
?>
<?php
$arr = array(new DbDisplay(), new FileDisplay());
foreach ($arr as $index => $obj) {
$obj->process();
echo "<hr>";
}
?>
出力結果はこちらのようになります。
PHPではJavaと異なり、abstractなメソッドの実装がConcreteClassで強制されないので、極端な話、AbstractClassに相当するクラスがなくても問題ないですが、あった方がわかりやすいと思います(手間ですが。。。)。
[2002/03/09] こちらに「abstractメソッドの実装を強制」させることについてまとめています
|