はじめに
Rx****をやってみたくなり、基本となる(?)ObserverパターンをPHPにて実装して見た。
前提条件として、
- PHP5.xでも動く
- ある程度実用的
とします。
Observerパターンとは
あちこちのページで書かれているので細かくは省略します。
状態変化に応じた処理を記述するときに有効らしいです。
今回のサンプル
タイトルと内容を入力とするフォームからPOSTされた時に、
- メール送信
- ログ出力
を行う処理を記述するのにObserverパターンで記述してみます。
(この程度でObserverパターンを使うのもって話はあるが。。。(汗)
クラス図はこんな感じ
ソース構成はこんな感じ
┣━ classes
┃ ┣━ ifSubject.php
┃ ┣━ clsFormdat.php
┃ ┣━ ifObserver.php
┃ ┣━ clsLogObserver.php
┃ ┣━ clsSndMailObserver.php
┗━ smp1.php
実装
インターフェイス
まずSubjectのインターフェイスは
ifSubject.php
<?php
/**
* Subjectインターフェイス
*/
interface ifSubject {
public function addObserver($obj); // Observerインスタンス追加
public function removeObserver($obj); // Observerインスタンス削除
public function notify(); // Observerへの通知
}
次にObserverインターフェイスは
ifObserver.php
<?php
/**
* Observerインターフェイス
*/
interface ifObserver {
public function execute($obj); // Subjectからの通知受信
}
Subjectクラス
clsFormdat.php
<?php
require_once(dirname(__FILE__)."/ifSubject.php");
/**
* フォームデータクラス
*/
class clsFormdat implements ifSubject {
private $title = ""; /// タイトル
private $memo = ""; /// 内容
private $arrObservers = NULL; /// Observerインスタンス配列
public function __construct() {
$this->arrObservers = array();
}
/**
* タイトルと内容のセッター
*/
public function __set($itm,$val) {
if ( $itm == "title" ) $this->title = $val;
if ( $itm == "memo" ) $this->memo = $val;
}
/**
* タイトルと内容のゲッター
*/
public function __get($itm) {
if ( $itm == "title" ) return $this->title;
if ( $itm == "memo" ) return $this->memo;
}
/**
* Observerインスタンス追加
* @param $obj Observerインスタンス
*/
public function addObserver($obj) {
$this->arrObservers[get_class($obj)] = $obj;
}
/**
* Observerインスタンス削除
* @param $obj Observerインスタンス
*/
public function removeObserver($obj) {
unset($this->arrObservers[get_class($obj)]);
}
/**
* Observerへの通知
*/
public function notify() {
foreach($this->arrObservers as $obj) {
$obj->execute($this);
}
}
}
Observerクラス
まず、ログ出力クラスは
clsLogObserver.php
<?php
require_once(dirname(__FILE__)."/ifObserver.php");
/**
* ログ出力クラス
*/
class clsLogObserver implements ifObserver {
public function __construct() {
}
/**
* 通知受信
* @param $obj clsFormdatのインスタンス
*/
public function execute($obj) {
$buf = "title:".$obj->title;
$buf .= "\n".$obj->memo;
$fp = fopen("/var/www/Log/app.log","a");
fwrite($fp,$buf);
fclose($fp);
}
}
次にメール送信クラス
clsSndMailObserver.php
<?php
require_once(dirname(__FILE__)."/ifObserver.php");
/**
* メール送信クラス
*/
class clsSndMailObserver implements ifObserver {
public function __construct() {
}
/**
* 通知受信
* @param $obj clsFormdatのインスタンス
*/
public function execute($obj) {
mail("tst@cde.jp",$obj->title,$obj->memo,"From: adm@cde.jp");
}
}
動かしてみる
次のコードで実際に動かしてみる。
smp1.php
<?php
require_once(dirname(__FILE__)."/classes/clsLogObserver.php");
require_once(dirname(__FILE__)."/classes/clsSndMailObserver.php");
require_once(dirname(__FILE__)."/classes/clsFormdat.php");
$obj = new clsFormdat();
$objLog = new clsLogObserver();
$obj->addObserver($objLog);
$objMail = new clsSndMailObserver();
$obj->addObserver($objMail);
$obj->title = "サンプルタイトル";
$obj->memo = "サンプルサンプル\nサンプル";
$obj->notify();
確かに実装はシンプルになったようだ。