<?php
/**
* 目的:代码的完善来说明从 基础类的调用到 工厂类的使用 再到容器的出现的原因
* (首先要明白工厂类和容器的关系 可以理解:容器就是工厂类的升级版(为了解决类的依赖))
* 如果不明白工厂类的往下看看,对比一下这几个例子,相信你就明白了。
* 下面举个例子:
* 简单模拟一个超人
* 1.一个超人 具备超人的能力(就是超人技能:如飞行 射击 扔炸弹 暴力攻击等能力)
* 2.从面向对象设计:首先分析应该分为超人类(Superman) 和超人技能类(Flight Shot UltraBomb等)
* 3.为了规范编程写一个技能接口类(Ability) 用来规范超人技能类(同上) 当然超人也可以写一个超人接口来规范超人,这里就不写了
* 4.看代码 先从没有涉及工厂类讲起,也就是最简单的类的直接调用 往下看
* 5.等一下:再说一下我要实现的是使用超人来拥有超人技能,我到底怎么实现的
*
*/ //超能力接口 作用:规范每个超人能力类
interface Ability
{
/**
* @Author shyn
* @DateTime 2017-12-20
* @param array $target [针对目标,可以使一个或多个,自己或他人]
* @return [type] [description]
* [超能力激活方法]
*/
public function activate(array $target);
} //飞翔能力
class Flight implements Ability
{
protected $speed;//速度
protected $holdtime;//飞行时间
protected $skill = '飞翔技能=';//技能描述
public function __construct($speed = 0, $holdtime = 0)
{
$this->speed = $speed;
$this->holdtime = $holdtime;
}
//激活该技能
public function activate(array $target)//参数可以忽略 保留待用
{
echo '超人飞行开始';
} //输出该类实例(就是对象实例 如:new Flight;) 显示信息
public function __toString()
{
return $this->skill.'速度:'.$this->speed.' 飞翔时间:'.$this->holdtime;
}
} //射击能力
class Shot{
protected $attack;//伤害
protected $range;//伤害范围
protected $skill = '射击技能=';//技能解说
public function __construct($attack = 0, $range = 0)
{
$this->attack = $attack;
$this->range = $range;
} //激活技能
public function activate(array $target)
{
echo '超人射击开始';
}
public function __toString()
{ return $this->skill.'伤害:'.$this->attack.' 射击距离:'.$this->range;
} } //暴击能力
class Force implements Ability
{
protected $attack;//伤害
protected $strength;//力量
protected $range;//范围
protected $skill;//技能标签
public function __construct($attack = 0, $range = 0, $strength = 0)
{
$this->attack = $attack;
$this->range = $range;
$this->strength = $strength;
} //激活暴击技能
public function activate(array $target)
{
echo '超人暴力攻击';
} public function __toString()
{
$this->skill = '暴力能力=';
return $this->skill.'伤害:'.$this->attack.' 力量:'.$this->strength.' 范围'.$this->range;
}
} //终极炸弹能力(扔炸弹)
class UltraBomb implements ability
{
protected $skill = '炸弹技能=';
protected $range;
protected $attack; public function __construct($range = 0 , $attack = 0)
{
$this->range = $range;
$this->attack = $attack; }
/**
* @Author shyn
* @DateTime 2017-12-20
* @param integer $bombRange [炸弹伤害范围]
* @param integer $attack [炸弹伤害程度]
* @return [type] [description]
* [使用炸弹]
*/
public function throwBomb($range = 5, $attack = 10){ echo '炸弹范围'.$range.'米 伤害为:'.$attack;
} public function activate(array $target)
{
echo '超人炸弹发射';
return $this;
} public function __toString()
{
return $this->skill.'伤害:'.$this->attack.' 爆炸范围:'.$this->range;
} } //超人类
class Superman
{
public $power = [];//用来保存超人技能 超人会有多个技能所以用数组 public function __construct(){
//重点在这里!!! 在没涉及到工厂类的时候,我们使用最简单的 超人技能类的调用类实现 超人拥有超人技能
//优点:简单明了一看就懂
//缺点:
//1.当涉及多个超人技能我们就得一个一个在这里写 从维护方面来说不妥
//2.当涉及到多个超人的时候我们还得在写一个这样的超人类 麻烦不 当然麻烦
//3.好,我们用工厂类来解决这个麻烦
$this->power =array(
'flight'=> new Flight(9, 10),//给超人添加飞行能力
'force' => new Force(33, 19, 20)//给超人添加暴力攻击能力
); } } $superman = new Superman();
$superman->power['flight']->activate([]);//超人开始飞行
echo'<br/>';
$superman->power['force']->activate([]);//超人开始飞行 ?>
 <?php

 //工厂类的使用
//超能力接口 作用:规范每个超人能力类
interface Ability
{
/**
* @Author shyn
* @DateTime 2017-12-20
* @param array $target [针对目标,可以使一个或多个,自己或他人]
* @return [type] [description]
* [超能力激活方法]
*/
public function activate(array $target);
} //飞翔能力
class Flight implements Ability
{
protected $speed;//速度
protected $holdtime;//飞行时间
protected $skill = '飞翔技能=';//技能描述
public function __construct($speed = 0, $holdtime = 0)
{
$this->speed = $speed;
$this->holdtime = $holdtime;
}
//激活该技能
public function activate(array $target = [])//参数可以忽略 保留待用
{
echo '超人飞行开始';
} //输出该类实例(就是对象实例 如:new Flight;) 显示信息
public function __toString()
{
return $this->skill.'速度:'.$this->speed.' 飞翔时间:'.$this->holdtime;
}
} //射击能力
class Shot{
protected $attack;//伤害
protected $range;//伤害范围
protected $skill = '射击技能=';//技能解说
public function __construct($attack = 0, $range = 0)
{
$this->attack = $attack;
$this->range = $range;
} //激活技能
public function activate(array $target = [])
{
echo '超人射击开始';
}
public function __toString()
{ return $this->skill.'伤害:'.$this->attack.' 射击距离:'.$this->range;
} } //暴击能力
class Force implements Ability
{
protected $attack;//伤害
protected $strength;//力量
protected $range;//范围
protected $skill;//技能标签
public function __construct($attack = 0, $range = 0, $strength = 0)
{
$this->attack = $attack;
$this->range = $range;
$this->strength = $strength;
} //激活暴击技能
public function activate(array $target = [])
{
echo '超人暴力攻击';
} public function __toString()
{
$this->skill = '暴力能力=';
return $this->skill.'伤害:'.$this->attack.' 力量:'.$this->strength.' 范围'.$this->range;
}
} //终极炸弹能力(扔炸弹)
class UltraBomb implements ability
{
protected $skill = '炸弹技能=';
protected $range;
protected $attack; public function __construct($range = 0 , $attack = 0)
{
$this->range = $range;
$this->attack = $attack; }
/**
* @Author shyn
* @DateTime 2017-12-20
* @param integer $bombRange [炸弹伤害范围]
* @param integer $attack [炸弹伤害程度]
* @return [type] [description]
* [使用炸弹]
*/
public function throwBomb($range = 5, $attack = 10){ echo '炸弹范围'.$range.'米 伤害为:'.$attack;
} public function activate(array $target = [])
{
echo '超人炸弹发射';
return $this;
} public function __toString()
{
return $this->skill.'伤害:'.$this->attack.' 爆炸范围:'.$this->range;
} } //超人技能工厂类
class abilityFactory{ public function makeSkill($moduleName , $optoin)
{
switch($moduleName){
case 'Flight':
return new Flight($optoin[0], $optoin[1]);
case 'Force':
return new Force($optoin[0]);
case 'Shot':
return new Shot($optoin[0], $optoin[1], $optoin[2]);
} }
} //超人类
class Superman
{
public $power = [];//用来保存超人技能 超人会有多个技能所以用数组 //初始化时传入传入技能类的名称
public function __construct(array $ability)
{
//这里使用超人能力工厂类
//优点:
//1.方便对技能的管理 直接在工厂里添加我们扩展的其他超人技能
//2.我们的超人类不用直接依赖我们的超人技能类
//缺点:
//1.不用直接依赖我们的超人技能类但是依赖了工厂类
//2.工厂类改变的话我们的超人技能必将受到影响
//3.有没有更好的方法来 当然有把这里理解后就可以继续往下看 我们的神器:容器(可称为超级工厂)
//4.容器是什么 不是什么 a.你可以理解一个更厉害的类 b.解决了超人类对工厂类的依赖
$af = new abilityFactory();//实例化工厂类
foreach ($ability as $abilityName => $abilityOptions) {
$this->power[] = $af->makeSkill($abilityName, $abilityOptions); }
} // 查看超人能力
public function __toString()
{
if(count($this->power)<1){
return '超人无能纳,还没任何技能';
}
foreach ($this->power as $key => $value) {
echo $key.'=>'.$value.'<br/>';
}
return '超人共有'.count($this->power).'个技能';
}
} $ability = ['Flight'=>[1,4]];//填写超人技能类名不区分大小写对应 能力工厂类中case
$superman = new Superman($ability); echo '<pre>';
var_dump($superman);//此时可以看到超人类中power 属性已经拥有该超人技能对象
$superman->power[0]->activate([]);//使用技能 看到这里完美 activate([]) 传递了一个空数组完全可以不需要 这里为了你可以传递技能参数故意添加的 可以自己试试搞一下 有些东西得练一下才好记得才明白
//继续往下看
?>
 <?php
//超能力接口 作用:规范每个超人能力类
interface Ability
{
/**
* @Author shyn
* @DateTime 2017-12-20
* @param array $target [针对目标,可以使一个或多个,自己或他人]
* @return [type] [description]
* [超能力激活方法]
*/
public function activate(array $target);
} //飞翔能力
class Flight implements Ability
{
protected $speed;//速度
protected $holdtime;//飞行时间
protected $skill = '飞翔技能=';//技能描述
public function __construct($speed = 0, $holdtime = 0)
{
$this->speed = $speed;
$this->holdtime = $holdtime;
}
//激活该技能
public function activate(array $target = [])//参数可以忽略 保留待用
{
echo '超人飞行开始';
} //输出该类实例(就是对象实例 如:new Flight;) 显示信息
public function __toString()
{
return $this->skill.'速度:'.$this->speed.' 飞翔时间:'.$this->holdtime;
}
} //射击能力
class Shot{
protected $attack;//伤害
protected $range;//伤害范围
protected $skill = '射击技能=';//技能解说
public function __construct($attack = 0, $range = 0)
{
$this->attack = $attack;
$this->range = $range;
} //激活技能
public function activate(array $target = [])
{
echo '超人射击开始';
}
public function __toString()
{ return $this->skill.'伤害:'.$this->attack.' 射击距离:'.$this->range;
} } //暴击能力
class Force implements Ability
{
protected $attack;//伤害
protected $strength;//力量
protected $range;//范围
protected $skill;//技能标签
public function __construct($attack = 0, $range = 0, $strength = 0)
{
$this->attack = $attack;
$this->range = $range;
$this->strength = $strength;
} //激活暴击技能
public function activate(array $target = [])
{
echo '超人暴力攻击';
} public function __toString()
{
$this->skill = '暴力能力=';
return $this->skill.'伤害:'.$this->attack.' 力量:'.$this->strength.' 范围'.$this->range;
}
} //终极炸弹能力(扔炸弹)
class UltraBomb implements ability
{
protected $skill = '炸弹技能=';
protected $range;
protected $attack; public function __construct($range = 0 , $attack = 0)
{
$this->range = $range;
$this->attack = $attack; }
/**
* @Author shyn
* @DateTime 2017-12-20
* @param integer $bombRange [炸弹伤害范围]
* @param integer $attack [炸弹伤害程度]
* @return [type] [description]
* [使用炸弹]
*/
public function throwBomb($range = 5, $attack = 10){ echo '炸弹范围'.$range.'米 伤害为:'.$attack;
} public function activate(array $target = [])
{
echo '超人炸弹发射';
return $this;
} public function __toString()
{
return $this->skill.'伤害:'.$this->attack.' 爆炸范围:'.$this->range;
} }
//超人类
class Superman
{
public $power = [];//超人技能 //超人改造 能力接口规范 遵循能力接口规范的才可以
public function __construct(Ability $ability = null)
{
//设置超人每个技能名字
if($ability != null){
$name = strtolower(get_class($ability));
$this->power[$name] = $ability;
}
}
/**
* @Author shyn
* @DateTime 2017-12-20
* @param [type] $ability [能力对象]
* [超人添加 二次添加其他能力]
*/
public function addAbility(Ability $ability)
{
$name = strtolower(get_class($ability));
$this->power[$name] = $ability; }
// 查看超人能力
public function __toString()
{
if(count($this->power)<1){
return '超人无能纳,还没任何技能';
}
foreach ($this->power as $key => $value) {
echo $key.'=>'.$value.'<br/>';
}
return '超人共有'.count($this->power).'个技能';
}
} //这里用到我们的神器:首先创建一个容器类
//工厂模式抛弃 制造一个更高级的工厂 容器(超级工厂)
/**
* 容器类的使用方法
* 1.有两个属性 两个方法
* 2.
*/
class Container
{
//$binds用于保存我们 不同绑定类传来的匿名函数(function(){} 并没有执行)
//如下面:保存为这样$binds['flight']=function(){};
public $binds;
public $instances; /**
* @Author shyn
* @DateTime 2017-12-20
* @param [type] $abstract ['初始对象实例名 用于保存在']
* @param [type] $concreate [匿名函数]
* @return [type] [description]
*/
public function bind($abstract, $concreate)
{
if($concreate instanceof Closure){
$this->binds[$abstract] = $concreate;
}else{
$this->instances[$abstract] = $concreate;
} } //执行绑定到$binds 中的function(){}
public function make($abstract, $parameters = [])
{
if(isset($this->instances[$abstract])){
return $this->instances[$abstract];
} array_unshift($parameters, $this);//将this 添加到数组 $parameters 用于call_user_func_array() 这点看@@清楚
// 将数组 $parameters 作为参数传递给回调函数$this->binds[$abstract] $abstract 是类名
return call_user_func_array($this->binds[$abstract], $parameters);
}
} // 创建一个容器 (超级工厂生成) 下面我们来把将要实例化的放进来
// 切记放进来并没有实例化 make()方法才开始实例化到执行
// 具体make() 函数看透就明白了 这点会有点绕 冷静下来接着干 往下看
$container = new Container(); //把超人技能 Flight类 保存在容器类(Container) $binds 属性中
//其实是保存的 function($container){return new Flight()} 并没有执行
//make 方法才是开始执行已经绑定到$binds 属性中的匿名函数【function(){}】
$container->bind('flight', function($container){
return new Flight();
}); //同上 记住这里只是绑定 到$binds 属性中 为了 下面使用
$container->bind('ultrabomb', function($container){
return new UltraBomb;
});
//同上 绑定到$binds 这里的function(){} 函数并没有执行 切记【强调】
$container->bind('Force', function($container){
return new Force;
});
// echo '<pre>';
// var_dump($container); 可以使用本句查看上面已经在 $container 中的绑定 //因为我们要使用我们的超人类(Superman)所以 也要绑定到容器
//作用:
//1.绑定到容器其实就是为了我们用容器的make()方法实例化Superman 然后使用
//2.不用我们在自己另外实例化,好处就是当我们要创造多个超人的时候 用容器来实例化多个超人就变得容易
$container->bind('superman', function($container, $ability){
// 下面的传参数为了拥有超人的 能力 这里是重点 仔细理解
return new Superman( $container->make($ability) );
}); //这里传入的参数superman 是根据上面 bind('super',function(){}) 方法传参定的 这里要和上面一样
//ultrabomb 对应的是 bind('ultrabomb',function(){})
$superman_1 = $container->make('superman', ['ultrabomb']);
echo '<pre>';
// var_dump($superman_1);//查看技能是否绑定到了$power
$superman_1->power['ultrabomb']->activate();//使用技能
// echo $superman_1; ?>

laravel 服务容器的由来 代码展示的更多相关文章

  1. laravel 服务容器

    服务容器,也叫IOC容器,其实包含了依赖注入(DI)和控制反转(IOC)两部分,是laravel的真正核心.其他的各种功能模块比如 Route(路由).Eloquent ORM(数据库 ORM 组件) ...

  2. Laravel 服务容器、服务提供器、契约实例讲解

        前言 刚开始看laravel服务容器.契约.服务提供器的确生涩难懂,不单单是概念繁多,而且实际的demo很难找(找是找到了,但难用啊),最后就隔一段时间看一遍,大概个十来遍,还真给看出个门道, ...

  3. Laravel 服务容器实例教程 —— 深入理解控制反转(IoC)和依赖注入(DI)

    容器,字面上理解就是装东西的东西.常见的变量.对象属性等都可以算是容器.一个容器能够装什么,全部取决于你对该容器的定义.当然,有这样一种容器,它存放的不是文本.数值,而是对象.对象的描述(类.接口)或 ...

  4. Laravel服务容器的绑定与解析

    本篇文章给大家带来的内容是关于Laravel服务容器的绑定与解析,有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助. 前言   老实说,第一次老大让我看laravel框架手册的那天早上,我 ...

  5. 关于使用 Laravel 服务容器的优势介绍

    如果说laravel框架的核心是什么,那么无疑是服务容器.理解服务容器的概念,对于我们使用laravel太重要了,应该说是否理解服务容器的概念是区分是否入门laravel的重要条件.因为整个框架正是在 ...

  6. laravel服务容器

    laravel框架底层解析 本文参考陈昊<Laravel框架关键技术解析>,搭建一个属于自己的简化版服务容器.其中涉及到反射.自动加载,还是需要去了解一下. laravel服务容器 建立项 ...

  7. laravel服务容器 转

    laravel框架底层解析 本文参考陈昊<Laravel框架关键技术解析>,搭建一个属于自己的简化版服务容器.其中涉及到反射.自动加载,还是需要去了解一下. laravel服务容器 建立项 ...

  8. laravel 服务容器实现原理

    前言 通过实现laravel 框架功能,以便深入理解laravel框架的先进思想. 什么是服务容器 服务容器是用来管理类依赖与运行依赖注入的工具.Laravel框架中就是使用服务容器来实现 ** 控制 ...

  9. laravel服务容器-----深入理解控制反转(IoC)和依赖注入(DI)

    首先大家想一想什么是容器,字面意思就是盛放东西的东西,常见的变量,对象属性都是容器,一个容器能够装什么东西,完全在于你对这个容器的定义.有的容器不仅仅只是存文本,变量,而是对象,属性,那么我们通过这种 ...

随机推荐

  1. $[SHOI2007]$ 园丁的烦恼 二维数点/树状数组

    \(Sol\) 设一个矩阵的左上角为\((x_1,y_1)\),右下角为\((x_2,y_2)\),\(s_{x,y}\)是到\((1,1)\)二维前缀和,那么这个矩阵的答案显然是\(s_{x_2,y ...

  2. [vsCode实践] 实践记录

    [vsCode实践] 实践记录 版权2019.5.1更新 Q1:代码中涉及到操作本地文件时,相对路径总是不对 操作本地文件时,路径方式有两种 相对路径 例如:代码文件所在路径/Users/tp0829 ...

  3. 如何让接口文档自动生成,SpringBoot中Swagger的使用

    目录 一.在SpringBoot项目中配置Swagger2 1.pom.xml中对Swagger2的依赖 2.编写配置类启用Swagger 3.配置实体类的文档 4.配置接口的文档 5.访问文档 二. ...

  4. 「CodeForces 546B」Soldier and Badges 解题报告

    CF546B Soldier and Badges 题意翻译 给 n 个数,每次操作可以将一个数 +1,要使这 n 个数都不相同, 求最少要加多少? \(1 \le n \le 3000\) 感谢@凉 ...

  5. 投票:OAuth2.0 技术选型你会怎么选

    1. 前言 在使用 OAuth2.0 中 Authorization Server (授权服务器)是一个回避不了的设施,在大多数情况下我们调用的是一些知名的.可靠的.可信任的第三方平台,比如 QQ.微 ...

  6. Cocos Creator | 飞刀大乱斗开发教程系列(三)

    预览效果 ​ 具体内容 ■ 这一期,主要讲解游戏过程中,通过触摸滑动,控制人物的运动方向,以及游戏过程中,人物运动区域的控制.如下图,人物通过滑动控制运动方向,即是往哪个方向滑动,人物就往哪个方向移动 ...

  7. Hyperledger Fabric1.4 安装

    Hyperledger Fabric 依赖的软件版本查看官方 github 地址 https://github.com/hyperledger/fabric 下文件 /docs/source/prer ...

  8. 【原理】从零编写ILI9341驱动全过程(基于Arduino)

    最近在淘宝入手了一块ILI9341彩色屏幕,支持320x240分辨率.之前一直很好奇这类单片机驱动的彩色屏幕的原理,就打算自己写一个驱动,从电流层面操控ILI9341屏幕.话不多说,我们开始吧( ̄▽ ̄ ...

  9. Java爬虫一键爬取结果并保存为Excel

    Java爬虫一键爬取结果并保存为Excel 将爬取结果保存为一个Excel表格 官方没有给出导出Excel 的教程 这里我就发一个导出为Excel的教程 导包 因为个人爱好 我喜欢用Gradle所以这 ...

  10. 使用gravatar生成头像

    avatar代表您在线的图像,当你与网站互动时,你的名字旁边会出现一张图片. Gravatar是一个全球通用的头像.你只需上传一次并创建自己的个人资料,然后当你加入任何支持Gravatar的网站时,你 ...