PHP設計模式之工廠模式
mount = $mount;
}
public function getAmount(){
return $this -> mount;
}
public function add($numbers = 200){
return new self($this-> mount+$numbers);
}
public function debit($numbers = 200){
if($this-> mount > $numbers){
return new self($this-> mount - $numbers);
}
return false;
}
}
/**
* 道具抽象類,規定了一些基本的道具所具有的共有的性質,例如擁有者、價格、
* 名稱、游戲名稱、可以出售、出租和購買,這些屬性和方法都是屬於道具共有
*/
abstract class Property{
protected $name;
protected $game;
protected $price;
protected $owner;
function __construct($owner,$game,$name,$price){
if(empty($owner)){echo '請輸入道具的擁有者姓名
';return ;}
echo '創建道具:所屬游戲:'.$game.',名稱:'.$name.',價格:'.$price.'
';
$this->owner= $owner;
$this->game = $game;
$this->name = $name;
$this->price =new Dollar($price);
}
/*道具的出租收取的租金,由具體的道具自己定義
租金公式:$rent_num=$tax_rate * $price;
*/
abstract protected function calcRent();
public function purcharse($player){
global $owners;
if($this-> owner ==$player-> name){
echo '你已經購買了該道具
';
}elseif($player -> salary->getAmount() < $this-> price-> getAmount() ){
echo '金幣不夠
';
}else{
$flag=$player->debit($this->price->getAmount());
if($flag){
$price=$this->price->getAmount();
$owners[$this->owner]->earnRent($price);
unset($owners[$this->owner]);
$this ->owner = $player->name;
$owners[$this->owner]=$player;
echo $player -> name.'購買道具:'.$this->game.$this->name.'成功
';
}else{
echo $player -> name.'購買道具:'.$this->game.$this->name.'失敗
';
}
}
}
public function __get($prop){
if(isset($this->$prop)){
return $this->$prop;
}
}
public function setRent($player){
global $owners;
if($player->name==$this->owner){echo '不能租用自己的道具
';return ;}
$price = $this-> calcRent();
$player->debit($price);
$owners[$this->owner]->earnRent($price);
echo $player->name.'租用道具成功';
return $price;
}
public function sell($player){
global $owners;
$price=$this->price->getAmount();
if($player -> salary-> getAmount() > $price){
echo '道具:'.$this-> game.$this->name.'-出售成功
';
//這裡實際上對應著數據庫的更新操作
$player->debit($price);
$owners[$this->owner]->earnRent($price);
unset($owners[$this->owner]);
$this->owner = $player->name;
$owners[$this->owner]=$player;
return $price;
}else{
echo '道具出售失敗
';
}
}
public function __toString(){
return $this->game.$this->owner.$this->name;
}
}
//一個模擬的游戲玩家類
class Player {
public $salary;
public $name;
public function __construct($name){
$this->salary = new Dollar(9000);
$this->name = $name;
}
//支出
public function debit($nums){
$price= $this->salary ->getAmount();
if($price < $nums){
echo '錢包的錢不夠了';
return false;
}
$flag=$this->salary-> debit($nums);
if($flag){
$this->salary = $flag;
return true;
}else{
return false;
}
}
//收入
public function earnRent($nums){
$this->salary-> add($nums);
}
}
//具體的道具類
class Street extends Property{
private $tax_rate=1;
public function __construct($owner,$game,$name,$price,$tax_rate){
parent::__construct($owner,$game,$name,$price);
$this-> tax_rate = $tax_rate;
}
//返回一個Dollar對象
public final function calcRent(){
return $this-> tax_rate * $this->price->getAmount();
}
}
class Rail extends Property{
private $tax_rate;
public function __construct($owner,$game,$name,$price,$tax_rate){
parent::__construct($owner,$game,$name,$price);
$this -> tax_rate = $tax_rate;
}
//返回一個Dollar對象
public final function calcRent(){
return $this-> tax_rate * $this->price->getAmount();
}
}
class Jet extends Property{
private $tax_rate;
public function __construct($owner,$game,$name,$price,$tax_rate){
parent::__construct($owner,$game,$name,$price);
$this-> tax_rate = $tax_rate;
}
//返回一個Dollar對象
public final function calcRent(){
return $this -> tax_rate * $this->price->getAmount();
}
}
//道具工廠類:制造所有的道具,但每個道具的tax_rate(稅率)是有定稅人(Taxer)
//來定的。實際項目中Taxer其實是個數據庫,存放了道具的價格,名稱等信息
//這個工廠就是工廠模式的核心,其通常是靜態方法的集合。並且實現了遲加載
//遲加載的含義:加載一個類只在創建它的時候才會去調用這個類文件。
class MonoLiSa{
//輸入參數$game和$name在實際項目中其實相當於
//數據庫中的主鍵id,只不過這裡沒有id所以用兩個字段
//代替,這個字段的含義就是數組的下標
static function createJoy($game,$game_id){
global $owners;
//查看“道具數據庫”中是否有相關信息
$info = Taxer::getInfo($game,$game_id);
if($info){
$owners[$info[2]]=new Player($info[2]);
return new $game_id($info[2],$game,$info[0],$info[1],$info[3]);
}
}
//重載系統魔術方法__autoload();
static function zhulk_autoload($className){
//指定加載默認的類文件
//如果有命名空間還要加載命名空間
$path = /usr/;
require_once $path.include/.$className.'.php';
}
}
//這個必須運行!
spl_autoload_register(array(MonoLiSa,zhulk_autoload));
//道具數據庫類:規定每個道具的名稱、價格、擁有人、租金稅率等信息,其作用相當於一個數據庫
final class Taxer{
static $db=array(
'game1'=>array(
'Street'=>array('芭蕉扇',1123.00,'鐵扇公主',0.23),
'Jet'=>array('金箍棒',3213.00,'孫悟空',0.23),
'Rail'=>array('傳送門',523.00,'暗黑巫師',0.23)
)
);
//獲取創建一個道具所需要的所有信息
//@params $game 道具所在游戲板塊
//@params $name 道具對應的類
static function getInfo($game,$game_id){
if(array_key_exists($game,self::$db) && array_key_exists($game_id,self::$db[$game]) ){
return self::$db[$game][$game_id];
}
return false;
}
}
//工廠實例創建對象流程
/*
1.查詢數據庫
2.工廠根據傳遞進來的參數創建具體的對象
3.返回創建的對象
工廠模式優點:用一個方法可以對要創建的對象進行控制。可以指定創建對象的類型
*/
//道具的擁有者組成的數組,以擁有者的名字為下標
$owners=array();
$obj1 = MonoLiSa::createJoy('game1','Street');
$obj2 = MonoLiSa::createJoy('game1','Jet');
$obj3 = MonoLiSa::createJoy('game1','Rail');
//道具被創建好了並被出售
echo $obj1;
echo '
'.$obj2; echo '
'.$obj3.'
'; //創建幾個使用者類 $player1= new Player(小紅); $player2= new Player(小虎); $player3= new Player(小花); $obj1-> purcharse($player1); $obj2-> purcharse($player2); $obj3-> purcharse($player3); $obj1-> setRent($player2); echo '
玩家的錢數'; echo '
'.$player1->name.':'.$player1->salary->getAmount(); echo '
'.$player2->name.':'.$player2->salary->getAmount(); echo '
'.$player3->name.':'.$player3->salary->getAmount();
在面向對象編程中, 最通常的方法是一個new操作符產生一個對象實例,new操作符就是用來構造對象實例的。但是在一些情況下, new操作符直接生成對象會帶來一些問題。舉例來說, 許多類型對象的創造需要一系列的步驟: 你可能需要計算或取得對象的初始設置; 選擇生成哪個子對象實例; 或在生成你需要的對象之前必須先生成一些輔助功能的對象。 在這些情況, 新對象的建立就是一個 “過程”,不僅是一個操作,像一部大機器中的一個齒輪傳動。