1 <?php 2 /** 3 * 目的:代码的完善来说明从 基础类的调用到 工厂类的使用 再到容器的出现的原因 4 * (首先要明白工厂类和容器的关系 可以理解:容器就是工厂类的升级版(为了解决类的依赖)) 5 * 如果不明白工厂类的往下看看,对比一下这几个例子,相信你就明白了。 6 * 下面举个例子: 7 * 简单模拟一个超人 8 * 1.一个超人 具备超人的能力(就是超人技能:如飞行 射击 扔炸弹 暴力攻击等能力) 9 * 2.从面向对象设计:首先分析应该分为超人类(Superman) 和超人技能类(Flight Shot UltraBomb等) 10 * 3.为了规范编程写一个技能接口类(Ability) 用来规范超人技能类(同上) 当然超人也可以写一个超人接口来规范超人,这里就不写了 11 * 4.看代码 先从没有涉及工厂类讲起,也就是最简单的类的直接调用 往下看 12 * 5.等一下:再说一下我要实现的是使用超人来拥有超人技能,我到底怎么实现的 13 * 14 */ 15 16 //超能力接口 作用:规范每个超人能力类 17 interface Ability 18 { 19 /** 20 * @Author shyn 21 * @DateTime 2017-12-20 22 * @param array $target [针对目标,可以使一个或多个,自己或他人] 23 * @return [type] [description] 24 * [超能力激活方法] 25 */ 26 public function activate(array $target); 27 } 28 29 //飞翔能力 30 class Flight implements Ability 31 { 32 protected $speed;//速度 33 protected $holdtime;//飞行时间 34 protected $skill = ‘飞翔技能=‘;//技能描述 35 public function __construct($speed = 0, $holdtime = 0) 36 { 37 $this->speed = $speed; 38 $this->holdtime = $holdtime; 39 } 40 //激活该技能 41 public function activate(array $target)//参数可以忽略 保留待用 42 { 43 echo ‘超人飞行开始‘; 44 } 45 46 //输出该类实例(就是对象实例 如:new Flight;) 显示信息 47 public function __toString() 48 { 49 return $this->skill.‘速度:‘.$this->speed.‘ 飞翔时间:‘.$this->holdtime; 50 } 51 } 52 53 54 //射击能力 55 class Shot{ 56 protected $attack;//伤害 57 protected $range;//伤害范围 58 protected $skill = ‘射击技能=‘;//技能解说 59 public function __construct($attack = 0, $range = 0) 60 { 61 $this->attack = $attack; 62 $this->range = $range; 63 } 64 65 //激活技能 66 public function activate(array $target) 67 { 68 echo ‘超人射击开始‘; 69 } 70 public function __toString() 71 { 72 73 return $this->skill.‘伤害:‘.$this->attack.‘ 射击距离:‘.$this->range; 74 } 75 76 } 77 78 //暴击能力 79 class Force implements Ability 80 { 81 protected $attack;//伤害 82 protected $strength;//力量 83 protected $range;//范围 84 protected $skill;//技能标签 85 public function __construct($attack = 0, $range = 0, $strength = 0) 86 { 87 $this->attack = $attack; 88 $this->range = $range; 89 $this->strength = $strength; 90 } 91 92 //激活暴击技能 93 public function activate(array $target) 94 { 95 echo ‘超人暴力攻击‘; 96 } 97 98 public function __toString() 99 { 100 $this->skill = ‘暴力能力=‘; 101 return $this->skill.‘伤害:‘.$this->attack.‘ 力量:‘.$this->strength.‘ 范围‘.$this->range; 102 } 103 } 104 105 //终极炸弹能力(扔炸弹) 106 class UltraBomb implements ability 107 { 108 protected $skill = ‘炸弹技能=‘; 109 protected $range; 110 protected $attack; 111 112 public function __construct($range = 0 , $attack = 0) 113 { 114 $this->range = $range; 115 $this->attack = $attack; 116 117 } 118 /** 119 * @Author shyn 120 * @DateTime 2017-12-20 121 * @param integer $bombRange [炸弹伤害范围] 122 * @param integer $attack [炸弹伤害程度] 123 * @return [type] [description] 124 * [使用炸弹] 125 */ 126 public function throwBomb($range = 5, $attack = 10){ 127 128 echo ‘炸弹范围‘.$range.‘米 伤害为:‘.$attack; 129 } 130 131 public function activate(array $target) 132 { 133 echo ‘超人炸弹发射‘; 134 return $this; 135 } 136 137 public function __toString() 138 { 139 return $this->skill.‘伤害:‘.$this->attack.‘ 爆炸范围:‘.$this->range; 140 } 141 142 } 143 144 145 //超人类 146 class Superman 147 { 148 public $power = [];//用来保存超人技能 超人会有多个技能所以用数组 149 150 public function __construct(){ 151 //重点在这里!!! 在没涉及到工厂类的时候,我们使用最简单的 超人技能类的调用类实现 超人拥有超人技能 152 //优点:简单明了一看就懂 153 //缺点: 154 //1.当涉及多个超人技能我们就得一个一个在这里写 从维护方面来说不妥 155 //2.当涉及到多个超人的时候我们还得在写一个这样的超人类 麻烦不 当然麻烦 156 //3.好,我们用工厂类来解决这个麻烦 157 $this->power =array( 158 ‘flight‘=> new Flight(9, 10),//给超人添加飞行能力 159 ‘force‘ => new Force(33, 19, 20)//给超人添加暴力攻击能力 160 ); 161 162 } 163 164 } 165 166 $superman = new Superman(); 167 $superman->power[‘flight‘]->activate([]);//超人开始飞行 168 echo‘<br/>‘; 169 $superman->power[‘force‘]->activate([]);//超人开始飞行 170 171 172 173 ?>
1 <?php 2 3 //工厂类的使用 4 //超能力接口 作用:规范每个超人能力类 5 interface Ability 6 { 7 /** 8 * @Author shyn 9 * @DateTime 2017-12-20 10 * @param array $target [针对目标,可以使一个或多个,自己或他人] 11 * @return [type] [description] 12 * [超能力激活方法] 13 */ 14 public function activate(array $target); 15 } 16 17 //飞翔能力 18 class Flight implements Ability 19 { 20 protected $speed;//速度 21 protected $holdtime;//飞行时间 22 protected $skill = ‘飞翔技能=‘;//技能描述 23 public function __construct($speed = 0, $holdtime = 0) 24 { 25 $this->speed = $speed; 26 $this->holdtime = $holdtime; 27 } 28 //激活该技能 29 public function activate(array $target = [])//参数可以忽略 保留待用 30 { 31 echo ‘超人飞行开始‘; 32 } 33 34 //输出该类实例(就是对象实例 如:new Flight;) 显示信息 35 public function __toString() 36 { 37 return $this->skill.‘速度:‘.$this->speed.‘ 飞翔时间:‘.$this->holdtime; 38 } 39 } 40 41 42 //射击能力 43 class Shot{ 44 protected $attack;//伤害 45 protected $range;//伤害范围 46 protected $skill = ‘射击技能=‘;//技能解说 47 public function __construct($attack = 0, $range = 0) 48 { 49 $this->attack = $attack; 50 $this->range = $range; 51 } 52 53 //激活技能 54 public function activate(array $target = []) 55 { 56 echo ‘超人射击开始‘; 57 } 58 public function __toString() 59 { 60 61 return $this->skill.‘伤害:‘.$this->attack.‘ 射击距离:‘.$this->range; 62 } 63 64 } 65 66 //暴击能力 67 class Force implements Ability 68 { 69 protected $attack;//伤害 70 protected $strength;//力量 71 protected $range;//范围 72 protected $skill;//技能标签 73 public function __construct($attack = 0, $range = 0, $strength = 0) 74 { 75 $this->attack = $attack; 76 $this->range = $range; 77 $this->strength = $strength; 78 } 79 80 //激活暴击技能 81 public function activate(array $target = []) 82 { 83 echo ‘超人暴力攻击‘; 84 } 85 86 public function __toString() 87 { 88 $this->skill = ‘暴力能力=‘; 89 return $this->skill.‘伤害:‘.$this->attack.‘ 力量:‘.$this->strength.‘ 范围‘.$this->range; 90 } 91 } 92 93 //终极炸弹能力(扔炸弹) 94 class UltraBomb implements ability 95 { 96 protected $skill = ‘炸弹技能=‘; 97 protected $range; 98 protected $attack; 99 100 public function __construct($range = 0 , $attack = 0) 101 { 102 $this->range = $range; 103 $this->attack = $attack; 104 105 } 106 /** 107 * @Author shyn 108 * @DateTime 2017-12-20 109 * @param integer $bombRange [炸弹伤害范围] 110 * @param integer $attack [炸弹伤害程度] 111 * @return [type] [description] 112 * [使用炸弹] 113 */ 114 public function throwBomb($range = 5, $attack = 10){ 115 116 echo ‘炸弹范围‘.$range.‘米 伤害为:‘.$attack; 117 } 118 119 public function activate(array $target = []) 120 { 121 echo ‘超人炸弹发射‘; 122 return $this; 123 } 124 125 public function __toString() 126 { 127 return $this->skill.‘伤害:‘.$this->attack.‘ 爆炸范围:‘.$this->range; 128 } 129 130 } 131 132 //超人技能工厂类 133 class abilityFactory{ 134 135 public function makeSkill($moduleName , $optoin) 136 { 137 switch($moduleName){ 138 case ‘Flight‘: 139 return new Flight($optoin[0], $optoin[1]); 140 case ‘Force‘: 141 return new Force($optoin[0]); 142 case ‘Shot‘: 143 return new Shot($optoin[0], $optoin[1], $optoin[2]); 144 } 145 146 } 147 } 148 149 150 //超人类 151 class Superman 152 { 153 public $power = [];//用来保存超人技能 超人会有多个技能所以用数组 154 155 //初始化时传入传入技能类的名称 156 public function __construct(array $ability) 157 { 158 //这里使用超人能力工厂类 159 //优点: 160 //1.方便对技能的管理 直接在工厂里添加我们扩展的其他超人技能 161 //2.我们的超人类不用直接依赖我们的超人技能类 162 //缺点: 163 //1.不用直接依赖我们的超人技能类但是依赖了工厂类 164 //2.工厂类改变的话我们的超人技能必将受到影响 165 //3.有没有更好的方法来 当然有把这里理解后就可以继续往下看 我们的神器:容器(可称为超级工厂) 166 //4.容器是什么 不是什么 a.你可以理解一个更厉害的类 b.解决了超人类对工厂类的依赖 167 $af = new abilityFactory();//实例化工厂类 168 foreach ($ability as $abilityName => $abilityOptions) { 169 $this->power[] = $af->makeSkill($abilityName, $abilityOptions); 170 171 } 172 } 173 174 // 查看超人能力 175 public function __toString() 176 { 177 if(count($this->power)<1){ 178 return ‘超人无能纳,还没任何技能‘; 179 } 180 foreach ($this->power as $key => $value) { 181 echo $key.‘=>‘.$value.‘<br/>‘; 182 } 183 return ‘超人共有‘.count($this->power).‘个技能‘; 184 } 185 } 186 187 $ability = [‘Flight‘=>[1,4]];//填写超人技能类名不区分大小写对应 能力工厂类中case 188 $superman = new Superman($ability); 189 190 echo ‘<pre>‘; 191 var_dump($superman);//此时可以看到超人类中power 属性已经拥有该超人技能对象 192 $superman->power[0]->activate([]);//使用技能 看到这里完美 activate([]) 传递了一个空数组完全可以不需要 这里为了你可以传递技能参数故意添加的 可以自己试试搞一下 有些东西得练一下才好记得才明白 193 //继续往下看 194 ?>
1 <?php 2 //超能力接口 作用:规范每个超人能力类 3 interface Ability 4 { 5 /** 6 * @Author shyn 7 * @DateTime 2017-12-20 8 * @param array $target [针对目标,可以使一个或多个,自己或他人] 9 * @return [type] [description] 10 * [超能力激活方法] 11 */ 12 public function activate(array $target); 13 } 14 15 //飞翔能力 16 class Flight implements Ability 17 { 18 protected $speed;//速度 19 protected $holdtime;//飞行时间 20 protected $skill = ‘飞翔技能=‘;//技能描述 21 public function __construct($speed = 0, $holdtime = 0) 22 { 23 $this->speed = $speed; 24 $this->holdtime = $holdtime; 25 } 26 //激活该技能 27 public function activate(array $target = [])//参数可以忽略 保留待用 28 { 29 echo ‘超人飞行开始‘; 30 } 31 32 //输出该类实例(就是对象实例 如:new Flight;) 显示信息 33 public function __toString() 34 { 35 return $this->skill.‘速度:‘.$this->speed.‘ 飞翔时间:‘.$this->holdtime; 36 } 37 } 38 39 40 //射击能力 41 class Shot{ 42 protected $attack;//伤害 43 protected $range;//伤害范围 44 protected $skill = ‘射击技能=‘;//技能解说 45 public function __construct($attack = 0, $range = 0) 46 { 47 $this->attack = $attack; 48 $this->range = $range; 49 } 50 51 //激活技能 52 public function activate(array $target = []) 53 { 54 echo ‘超人射击开始‘; 55 } 56 public function __toString() 57 { 58 59 return $this->skill.‘伤害:‘.$this->attack.‘ 射击距离:‘.$this->range; 60 } 61 62 } 63 64 //暴击能力 65 class Force implements Ability 66 { 67 protected $attack;//伤害 68 protected $strength;//力量 69 protected $range;//范围 70 protected $skill;//技能标签 71 public function __construct($attack = 0, $range = 0, $strength = 0) 72 { 73 $this->attack = $attack; 74 $this->range = $range; 75 $this->strength = $strength; 76 } 77 78 //激活暴击技能 79 public function activate(array $target = []) 80 { 81 echo ‘超人暴力攻击‘; 82 } 83 84 public function __toString() 85 { 86 $this->skill = ‘暴力能力=‘; 87 return $this->skill.‘伤害:‘.$this->attack.‘ 力量:‘.$this->strength.‘ 范围‘.$this->range; 88 } 89 } 90 91 //终极炸弹能力(扔炸弹) 92 class UltraBomb implements ability 93 { 94 protected $skill = ‘炸弹技能=‘; 95 protected $range; 96 protected $attack; 97 98 public function __construct($range = 0 , $attack = 0) 99 { 100 $this->range = $range; 101 $this->attack = $attack; 102 103 } 104 /** 105 * @Author shyn 106 * @DateTime 2017-12-20 107 * @param integer $bombRange [炸弹伤害范围] 108 * @param integer $attack [炸弹伤害程度] 109 * @return [type] [description] 110 * [使用炸弹] 111 */ 112 public function throwBomb($range = 5, $attack = 10){ 113 114 echo ‘炸弹范围‘.$range.‘米 伤害为:‘.$attack; 115 } 116 117 public function activate(array $target = []) 118 { 119 echo ‘超人炸弹发射‘; 120 return $this; 121 } 122 123 public function __toString() 124 { 125 return $this->skill.‘伤害:‘.$this->attack.‘ 爆炸范围:‘.$this->range; 126 } 127 128 } 129 //超人类 130 class Superman 131 { 132 public $power = [];//超人技能 133 134 //超人改造 能力接口规范 遵循能力接口规范的才可以 135 public function __construct(Ability $ability = null) 136 { 137 //设置超人每个技能名字 138 if($ability != null){ 139 $name = strtolower(get_class($ability)); 140 $this->power[$name] = $ability; 141 } 142 } 143 /** 144 * @Author shyn 145 * @DateTime 2017-12-20 146 * @param [type] $ability [能力对象] 147 * [超人添加 二次添加其他能力] 148 */ 149 public function addAbility(Ability $ability) 150 { 151 $name = strtolower(get_class($ability)); 152 $this->power[$name] = $ability; 153 154 } 155 // 查看超人能力 156 public function __toString() 157 { 158 if(count($this->power)<1){ 159 return ‘超人无能纳,还没任何技能‘; 160 } 161 foreach ($this->power as $key => $value) { 162 echo $key.‘=>‘.$value.‘<br/>‘; 163 } 164 return ‘超人共有‘.count($this->power).‘个技能‘; 165 } 166 } 167 168 169 //这里用到我们的神器:首先创建一个容器类 170 //工厂模式抛弃 制造一个更高级的工厂 容器(超级工厂) 171 /** 172 * 容器类的使用方法 173 * 1.有两个属性 两个方法 174 * 2. 175 */ 176 class Container 177 { 178 //$binds用于保存我们 不同绑定类传来的匿名函数(function(){} 并没有执行) 179 //如下面:保存为这样$binds[‘flight‘]=function(){}; 180 public $binds; 181 public $instances; 182 183 /** 184 * @Author shyn 185 * @DateTime 2017-12-20 186 * @param [type] $abstract [‘初始对象实例名 用于保存在‘] 187 * @param [type] $concreate [匿名函数] 188 * @return [type] [description] 189 */ 190 public function bind($abstract, $concreate) 191 { 192 if($concreate instanceof Closure){ 193 $this->binds[$abstract] = $concreate; 194 }else{ 195 $this->instances[$abstract] = $concreate; 196 } 197 198 } 199 200 //执行绑定到$binds 中的function(){} 201 public function make($abstract, $parameters = []) 202 { 203 if(isset($this->instances[$abstract])){ 204 return $this->instances[$abstract]; 205 } 206 207 array_unshift($parameters, $this);//将this 添加到数组 $parameters 用于call_user_func_array() 这点看@@清楚 208 // 将数组 $parameters 作为参数传递给回调函数$this->binds[$abstract] $abstract 是类名 209 return call_user_func_array($this->binds[$abstract], $parameters); 210 } 211 } 212 213 214 // 创建一个容器 (超级工厂生成) 下面我们来把将要实例化的放进来 215 // 切记放进来并没有实例化 make()方法才开始实例化到执行 216 // 具体make() 函数看透就明白了 这点会有点绕 冷静下来接着干 往下看 217 $container = new Container(); 218 219 //把超人技能 Flight类 保存在容器类(Container) $binds 属性中 220 //其实是保存的 function($container){return new Flight()} 并没有执行 221 //make 方法才是开始执行已经绑定到$binds 属性中的匿名函数【function(){}】 222 $container->bind(‘flight‘, function($container){ 223 return new Flight(); 224 }); 225 226 //同上 记住这里只是绑定 到$binds 属性中 为了 下面使用 227 $container->bind(‘ultrabomb‘, function($container){ 228 return new UltraBomb; 229 }); 230 //同上 绑定到$binds 这里的function(){} 函数并没有执行 切记【强调】 231 $container->bind(‘Force‘, function($container){ 232 return new Force; 233 }); 234 // echo ‘<pre>‘; 235 // var_dump($container); 可以使用本句查看上面已经在 $container 中的绑定 236 237 238 239 //因为我们要使用我们的超人类(Superman)所以 也要绑定到容器 240 //作用: 241 //1.绑定到容器其实就是为了我们用容器的make()方法实例化Superman 然后使用 242 //2.不用我们在自己另外实例化,好处就是当我们要创造多个超人的时候 用容器来实例化多个超人就变得容易 243 $container->bind(‘superman‘, function($container, $ability){ 244 // 下面的传参数为了拥有超人的 能力 这里是重点 仔细理解 245 return new Superman( $container->make($ability) ); 246 }); 247 248 249 //这里传入的参数superman 是根据上面 bind(‘super‘,function(){}) 方法传参定的 这里要和上面一样 250 //ultrabomb 对应的是 bind(‘ultrabomb‘,function(){}) 251 $superman_1 = $container->make(‘superman‘, [‘ultrabomb‘]); 252 echo ‘<pre>‘; 253 // var_dump($superman_1);//查看技能是否绑定到了$power 254 $superman_1->power[‘ultrabomb‘]->activate();//使用技能 255 // echo $superman_1; 256 257 258 259 260 261 262 263 264 265 ?>