下面实现了查人拥有超能力的三种方式
第一种最基本的类引用实现
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 ?>
from:https://www.insp.top/learn-laravel-container 已整理