控制反转(简称IoC),是一种面向对象的设计思想,用来下降代码间的耦合度。经过控制反转,对象在被建立的时候,由一个调控系统内全部对象的外界实体,将其所依赖的对象的引用传递给它。也就是将依赖被注入到要调用的对象中。控制反转通常和容器思想结合使用,Ioc就是将对象交给容器去控制,而不是在对象内部直接控制,主要是控制对象的内部依赖。
php
IoC经过一个专门的容器来建立对象,经过IoC容器来控制对象laravel
控制实例的外部依赖编程
关于反转设计模式
IoC是一种面向对象的变成思想和指导准则。解决传统控制正转开发中在类内部主动建立依赖类,从而致使类的内部耦合,难以复用。IoC把查找建立依赖的控制权反转给容器,由容器进行注入来组合建立一个对象,不一样需求容器能够注入不一样的对象,从而消除对象和依赖的耦合。数组
依赖注入指容器在运行中动态的将依赖注入到组件中,从而使组件具备具体的功能。经过依赖注入能够在特殊的地方指定同一个抽象方法去处理不一样依赖对象的逻辑,而不须要了解和修改具体抽象方法的实现,只须要关注本身的业务层。框架
实例化类依赖控制容器函数
实例化类须要依赖其余资源才能够处理具体业务this
IoC容器向实例化类中注入了某个依赖spa
set
方法。实现特定属性的 public set
方法,来让外部容器调用传入所依赖类型的对象。interface Way { public function go(); } class GoShanghai { private $charger; public function __construct(Way $charger) { $this->charger = $charger; } public function setWay(Way $way) { $this->way = $way; } public function go() { $this->charger->go(); } } class Car implements Way { public function go() { // TODO: Implement go() method. print_r("我经过开车去上海"); } }
// 基于构造函数和接口 $goshanghai = new GoShanghai(new Car()); $goshanghai->go(); // 基于set方法|展现须要由于构造函数运行会出错 $goshanghai = new GoShanghai(); $goshanghai->setWay(new Car()); $goshanghai->go();
依赖查找更加主动,在须要的时候经过调用框架提供的方法来获取对象,获取时须要提供相关的配置文件路径、key等信息来肯定获取对象的状态。
观察者模式主要用于处理对象直接一对多多关系。当外部资源发生改变,观察者会获得通知。观察者和被观察者直接是抽象耦合的,也就不影响实例的解藕。
观察者是一对多关系中的多,观察者须要根据目标对象改变而改变的对象。
观察目标对象的某些特定的状态。
观察者继承自一个抽象观察类,抽象观察类实现注册、监听和通知功能。
/** * 观察者的抽象类 */ abstract class Observer { // 这是一个目标类 protected $subject; // 定义一个用于更新的抽象方法 public abstract function update(); } /** * 目标类 */ class Subject { // 观察者数组集合 private $observerList = array(); // 状态,这里遵循开闭原则将属性私有化 private $state = 0; /** * 获取状态的值 */ public function getState() :int { return $this->state; } /** * 设置状态的值 * @param int $state */ public function setState(int $state) { $this->state = $state; $this->notifyAllObservers(); } /** * 注册观察者 * @param Observer $observer */ public function attach(Observer $observer) { array_push($this->observerList, $observer); } /** * 通知观察者 */ public function notifyAllObservers() { foreach ($this->observerList as $observer) { $observer->update(); } } } /** * 观察者A */ class AObserver extends Observer { public function __construct(Subject $subject) { // 注入目标依赖实现IoC $this->subject = $subject; // 注册观察者 $this->subject->attach($this); } public function update() { // TODO: Implement update() method. print_r("A观察者更新了支付业务的状态:{$this->subject->getState()}\n"); } }
// 建立一个目标对象 $subject = new Subject(); // 为目标对象绑定观察者 new AObserver($subject); print_r("目标对象的状态:{$subject->getState()}\n"); $subject->setState(10); // 目标对象的状态:0 // A观察者更新了支付业务的状态:10
经过一个抽象基类定义执行它的模版也能够是方法,子类重写抽象方法的实现,但调用实在抽象基类中完成的,从而实现控制反转。就是基类控制行为,子类完成实现。
/** * 抽象模版类 */ abstract class Template { // 抽象方法A public abstract function stepA(); // 抽象方法B public abstract function stepB(); // 执行定义的步骤, 这里使用了final关键字修饰,final的做用是使这个方法不可被继承, 这样就不会被子类执行 public final function run() { $this->stepA(); $this->stepB(); } } /** * 方案A的实例 */ class FuncA extends Template { public function stepA() { // TODO: Implement stepA() method. print_r("方案A第一步\n"); } public function stepB() { // TODO: Implement stepB() method. print_r("方案A第二步\n"); } }
$funca = new FuncA(); $funca->run();
上面的例子能够看到控制反转使每一个业务实例相对对立,他们的组装在代码执行时完成,当业务简单、依赖单一时看上去没有问题,可是当依赖复杂时会致使组装变得繁琐且难以梳理。在laravel中是经过容器Container
来解决这个问题。下面咱们经过几句话来简单看一下laravel中容器的使用。
laravel
时就是启动了一个容器make
实现自动序列化依赖对象,代替new
bind
方法让每个抽象接口和它的实例类一一对应resolveing
方法注册一个回调callback
在绑定的对象解析完以后调用