オブジェクト指向をあえて車クラスタ目線で書いてみた

Redさんのエントリを見てちょっとオブジェクト化について書いてみた。

kamiyamという車好きな人のお話に置き換えてみました^^;
ここで定義するクラスはある車屋さんです。
この車屋さんをオブジェクトとして捉えてみましょう。

【クラス定義】

BetaAuto.php

ある車屋さん『ベータオート』さんが外向けの業務として受けつけている仕事は次の5つ (※言い換えると、クラスBetaAutoが、外部公開(public)している関数は次の5つ) ○getNewCarMitumori($carname)   車名から見積もり金額を返す。 ○deliverNewCar($personname, $carname)   車の納車。   だだし、ここでお金のやり取りはしていません。 ○getSeikyu($personname)   顧客名から請求金額を返す ○payMoney( $personname, $money )   顧客から金額を受け取り精算する ○doSyaken(&$Car)   車を車検整備する。   中で色々整備してます。

<?php
class BetaAuto
{
//請求リスト
private $_SeikyuList;

//見積りリスト
private $_MitumoriList;

//売り上げ
private $_Uriage;

//バイヤーさんオブジェクト
private	$_Buyer;

/**
* コンストラクタ
*/
public function __construct()
{
//初期化
$this->$_Uriage = 0;
$this->$_SeikyuList = array();
$this->$_MitumoriList = array();
$this->$_Buyer = new Buyer();
}

/**
* 見積もり額を返す
*/
public function getNewCarMitumori( $carname )
{
//バイヤーから見積もりを取り、手数料加算
$mitumori = $this->getBuyerMitumori ( $carname ) * 1.5;
//見積もりリストに格納
$this->$_MitumoriList += array( $carname => $mitumori );
return $mitumori;
}

/**
* バイヤーから見積もりを取る
*/
private function getBuyerMitumori( $carname )
{
return  $this->$_Buyer->getMitumori( $carname );
}

/**
* 車を納車する(車オブジェクト返す)
* 金額のやり取りは無し
*/
public function deliverNewCar( $personname, $carname )
{
//バイヤーから車を受け取る
$Car = $this->$_Buyer->deliverNewCar ( $carname );

//メンテナンスしてみたり
$Car->Mentenance();

//請求リストに加算
$this->$_SeikyuList[$personname] += $this->$_MitumoriList[$carname];
return ( $Car );
}

/**
* 精算する
*/
public function payMoney( $personname, $money )
{
//売り上げ計上
$this->$_Uriage += $money;

//請求額から減算
$this->$_SeikyuList[$personname] -= $money;
}

/**
* 車検とか
*/
public function doSyaken( &$Car )
{
//タイヤとか調べる
if ( $Car->isEndLife("tire") )
{
//タイヤ交換したり
$Car->doChange( "tire" );
$tires = 20 * 1000;

//請求リストに加算
$personname = $car->Owener;
$this->$_SeikyuList[$personname] += tires;
}
}

/**
* 請求額を返す
*/
public function getSeikyu( $personname )
{
return ( $this->$_SeikyuList[$personname] );
}
}

?>

今回あえてBetaAutoで親クラスとインターフェイスは定義していません。

■コンストラクタ
○__construct() 新装オープンしたので ・売上の初期化 ・請求リストの初期化 ・見積りリストの初期化 ・バイヤーさん(オブジェクト)の呼び出し なんかの手続きを内部で行いました。
■関数処理
○getNewCarMitumori($carname) 新しい車の見積もりですね。 ・バイヤーから業者販売価格に見積り ・手数料として50%増ししています。 これが本当なら美味しい商売ですね。

○deliverNewCar($personname, $carname)
車(オブジェクト)の納車です。
・バイヤーに車を手配してもらいました。
・車のメンテナンス
・顧客への請求を計上

車を顧客に引き渡しましょう。

○getSeikyu($personname)
顧客名から請求金額を返す。
・顧客の名前から請求金額リスト(メンバー変数)を出す。
・そして返却

○payMoney($personname)
会計処理
・顧客名から請求金額を出す。
・請求金額トータルから減算。
・売上金に加算

○doSyaken(&$Car)
車の車検です。
車オブジェクトを参照渡しで引き取りました。
参照なので参照元とリンクした状態です。
この関数内での車への整備は参照元にも反映されますね。

画面処理

PersonLife.php

■処理フロー
・kamiyamという人がベータオートさんをよびました。 ・RX-7の見積もりを依頼 ・見積もり金額を元に悩む ・車の納車 ・車両代金精算 ・色々なところを走る ・車検 ・請求聞く ・オワタ

<?php

//kamiyam情報
$person = "kamiyam";
$iWantCar = "RX-7";
$saifu = 3 * 1000 * 1000;

//車屋さんオブジェクト召喚
$Auto = new BetaAuto();

//見積もりを取ってみる
$mitumori = $Auto->getNewCarMitumori( iWantCar );
if ( $mitumori > 2 * 1000 * 1000 )
{
//高いのであきらめる
return;
}

//車を買う

//納車
$Car = $Auto->deliverNewCar( $person, $iWantCar );

//代金支払い
$seikyu = $Auto->getSeikyu( $person );
$Auto->payMoney( $seikyu );
$saifu -= $seikyu;

//走らせる走らせる
$Car->Run();
$Car->Run();
$Car->Run();

//休み
if ( $isHoliday )
{
//たまにはサーキット
$Car->Circuit_Run();
}

//車検だ
if( $Car->isSyaken )
{
//車検に出す。
$Auto->doSyaken( $Car );
}

//請求聞く
$seikyu2 = $Auto->getSeikyu( $person );
if( $seikyu2 > $saifu )
{
//\(^o^)/
}
else
{
$Auto->payMoney( $seikyu2 );
$saifu -= $seikyu2;
}
?>

ここでのポイントは2つ

オブジェクト化

車屋さんを一つのオブジェクトとしているので、違う場面(画面処理)でもnewして呼び出せばいいだけです。

実はBuyerとCarもオブジェクトになっているんですが、イメージとしてとらえやすいと思います。
コードもシンプルです。
開発時には分業も可能となります。

アクセス修飾子

アクセス修飾子『private』の使いどころ。
○メンバー変数(一部抜粋)
 private $_SeikyuList
○関数
 private getBuyerMitumori($carname)

上のメンバー変数/関数はprivateとなっているため、このBetaAutoオブジェクトを生成したPersonLife.php側では呼び出せません。
これが『public』だったらどうなるでしょう。

○$_SeikyuList

//車を買う
$Car = $Auto->getNewCar( $person, $iWantCar );
//請求リストの値を0に
$Auto->$_SeikyuList[$personname] = 0;
//請求を聞く
$seikyu = $Auto->getSeikyu( $person );

あら、車屋さんの内部で管理している請求リストを改ざんしちゃいました。
請求金額は0円です。
ダダで車が購入出来ちゃいました。

○getBuyerMitumori($carname)

//見積もり
$mitumori = $Auto->getNewCarMitumori( iWantCar );
$gyouhan = $Auto->getBuyerMitumori( iWantCar );

$sagaku = $mitumori - $gyouhan;

顧客が業販価格を知ってしまいました。
差額まで計算しています。
あまり顧客に業販価格を知る術を提供しちゃまずいですよね。
(※今はネットで調べれば、業販価格とかは判明しちゃいますが・・・)

なので、車屋さんの中で処理すべき書類や手続き(メンバー変数や関数)は非公開(private)にすると良いですね。。。

以上、オブジェクト化とアクセス修飾子について書いてみました。
これを書いているうちに今回と同じ車目線で継承/オーバーライドのネタが出来たので次回があればまた。

【さいごに】

PHPはあまり分からないので連想配列の使い方とか間違ってるかも。。。 サンプルコードは実際に動作していないためもしかしたら記述ミスとかあるかも知れません。