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