PHP设计模式之工厂模式
<?php class Dollar{ private $mount; public function __construct($mount=200){ $this->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 '请输入道具的拥有者姓名<br />';return ;} echo '创建道具:所属游戏:'.$game.',名称:'.$name.',价格:'.$price.'<br />'; $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 '你已经购买了该道具<br />'; }elseif($player -> salary->getAmount() < $this-> price-> getAmount() ){ echo '金币不够<br />'; }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.'成功<br />'; }else{ echo $player -> name.'购买道具:'.$this->game.$this->name.'失败<br />'; } } } public function __get($prop){ if(isset($this->$prop)){ return $this->$prop; } } public function setRent($player){ global $owners; if($player->name==$this->owner){echo '不能租用自己的道具<br />';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.'-出售成功<br />'; //这里实际上对应着数据库的更新操作 $player->debit($price); $owners[$this->owner]->earnRent($price); unset($owners[$this->owner]); $this->owner = $player->name; $owners[$this->owner]=$player; return $price; }else{ echo '道具出售失败<br />'; } } 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 '<hr />'.$obj2; echo '<hr />'.$obj3.'<hr />'; //创建几个使用者类 $player1= new Player("小红"); $player2= new Player("小虎"); $player3= new Player("小花"); $obj1-> purcharse($player1); $obj2-> purcharse($player2); $obj3-> purcharse($player3); $obj1-> setRent($player2); echo '<hr />玩家的钱数'; echo '<br />'.$player1->name.':'.$player1->salary->getAmount(); echo '<br />'.$player2->name.':'.$player2->salary->getAmount(); echo '<br />'.$player3->name.':'.$player3->salary->getAmount();
在面向对象编程中, 最通常的方法是一个new操作符产生一个对象实例,new操作符就是用来构造对象实例的。但是在一些情况下, new操作符直接生成对象会带来一些问题。举例来说, 许多类型对象的创造需要一系列的步骤: 你可能需要计算或取得对象的初始设置; 选择生成哪个子对象实例; 或在生成你需要的对象之前必须先生成一些辅助功能的对象。 在这些情况, 新对象的建立就是一个 “过程”,不仅是一个操作,像一部大机器中的一个齿轮传动。
工厂模式封装了对象的建立过程。 你可以在对象本身创建对象工厂或者是一个额外的工厂类。下面是一个具体的实例
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。