首页 > 代码库 > PHP设计模式之工厂模式

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操作符直接生成对象会带来一些问题。举例来说, 许多类型对象的创造需要一系列的步骤: 你可能需要计算或取得对象的初始设置; 选择生成哪个子对象实例; 或在生成你需要的对象之前必须先生成一些辅助功能的对象。 在这些情况, 新对象的建立就是一个 “过程”,不仅是一个操作,像一部大机器中的一个齿轮传动。

工厂模式封装了对象的建立过程。 你可以在对象本身创建对象工厂或者是一个额外的工厂类。下面是一个具体的实例

PHP设计模式之工厂模式