美文网首页Yii2yii2Yii2
Yii2框架源码研究3-ServiceLocator

Yii2框架源码研究3-ServiceLocator

作者: Vos井宝 | 来源:发表于2016-04-13 16:45 被阅读273次

ServiceLocator类继承了Component类和Object类的所有特性,也就是说他现在拥有了属性,时间和行为这三个武器。服务定位器是一种设计模式,使用它的目的就是解耦,使得服务请求方不需要直接对服务提供者进行操作,只需要告诉服务定位器我现在想要什么服务,服务定位器就能够定位到能够提供这个服务的组件。
  从直观的角度理解,假如现在我想发送一个邮件,如果没有采用服务定位器这样的设计方法,那我现在肯定需要在现在的代码里面,将发送邮件的这个组件进行实例化,然后进行发送邮件的操作。但是有时候突然发现这个发送邮件的组件不好用,需要换一个,那就必须要修改我的代码了,这样一来二去的就很烦人,因为对于客户端来说,他只是仅仅想发送一个邮件,提供服务的组件不好用了竟然还得需要让他来修改代码。
  服务定位器的出现打破了这个状况,我现在只要告诉服务定位器我想要发送一个邮件,那么服务定位器就能提供我需要的组件,我拿过来直接用就可以了,如果这个组件想换了,只需要在服务定位器这里将发送邮件这个服务定位到其他的某一个发送邮件的组件就可以了,客户端的代码根本不需要改变。
  现在就来分析一下服务定位器这个模式需要什么要素。想来想去还真的好简单,不就是一个数组就行了嘛!key为组件名称,value为提供组件的类。接下来就看看在Yii框架中这个类是怎么实现的吧!

class ServiceLocator extends Component
{
    private $_components = [];
    private $_definitions = [];
    public function __get($name)
    {
        if ($this->has($name)) {
            return $this->get($name);
        } else {
            return parent::__get($name);
        }
    }
    public function __isset($name)
    {
        if ($this->has($name, true)) {
            return true;
        } else {
            return parent::__isset($name);
        }
    }
    public function has($id, $checkInstance = false)
    {
        return $checkInstance ? isset($this->_components[$id]) : isset($this->_definitions[$id]);
    }
    public function get($id, $throwException = true)
    {
        if (isset($this->_components[$id])) {
            return $this->_components[$id];
        }

        if (isset($this->_definitions[$id])) {
            $definition = $this->_definitions[$id];
            if (is_object($definition) && !$definition instanceof Closure) {
                return $this->_components[$id] = $definition;
            } else {
                return $this->_components[$id] = Yii::createObject($definition);
            }
        } elseif ($throwException) {
            throw new InvalidConfigException("Unknown component ID: $id");
        } else {
            return null;
        }
    }
    public function set($id, $definition)
    {
        if ($definition === null) {
            unset($this->_components[$id], $this->_definitions[$id]);
            return;
        }
        unset($this->_components[$id]);

        if (is_object($definition) || is_callable($definition, true)) {
            // an object, a class name, or a PHP callable
            $this->_definitions[$id] = $definition;
        } elseif (is_array($definition)) {
            // a configuration array
            if (isset($definition['class'])) {
                $this->_definitions[$id] = $definition;
            } else {
                throw 
            }
        } else {
            throw 
        }
    }
    public function clear($id)
    {
        unset($this->_definitions[$id], $this->_components[$id]);
    }
    public function getComponents($returnDefinitions = true)
    {
        return $returnDefinitions ? $this->_definitions : $this->_components;
    }
    public function setComponents($components)
    {
        foreach ($components as $id => $component) {
            $this->set($id, $component);
        }
    }
}

看着好简单,最后的两个set和get函数用来实现components属性,也就是说,ServiceLocator的配置数组里面有一个key为components,并且这个key也对应了一个数组,数组的每一项是key=>value类型的,key为组件名称,value包含了提供组件的类。
  ServiceLocator中有两个数组来存储组件,一个是$_definitions,用于直接存储配置数组里面的内容,里面有可能仅仅存储了提供组件的类的名称。一个是$_components,里面是提供组件的类的实例。
  两个函数get()和set()就是用来获取服务和设置服务的,设置服务的时候一开始并没有将提供服务的类实例化,只有当获取到某一个服务的时候,如果提供这个服务的类没有被实例化,他才会被实例化,get()函数会返回这个对象。

相关文章

  • Yii2框架源码研究3-ServiceLocator

    ServiceLocator类继承了Component类和Object类的所有特性,也就是说他现在拥有了属性,时间...

  • Yii2框架源码研究1-Object

    继承树分析 看yii2框架的源代码会发现,请求的入口,也就是index.php文件,相当的简单,在入口文件中有一行...

  • Yii2框架源码研究2-Component

    Component继承自Object,因此他具有属性这个特性,在这个基础上,组件提供了两个功能强大的特性:事件和行...

  • yii2框架源码分析系列(1)之入口

    写在开始 用了yii2框架也有一年的时间了,挺喜欢yii2的,期间也根据工作需要看过一些源码,在此写一个系列的文章...

  • Yii2 PHP框架

    自动加载函数 Yii2 PHP框架学习记录--自动加载函数 常量 Yii2 PHP框架学习记录-常量 $_SERV...

  • yii2 搭建测试环境

    yii2 本身集成了Codeception 测试框架,那么我们就在 yii2 中使用 Codeception 来做...

  • php 递归一棵树

    基于yii2框架: controller: public function actionDigui() { $...

  • 用发展的眼光追技术

    本文从 PHP 语言的 YII2 框架说起,简单谈一些技术的演变和发展脉络。 YII2 这个框架是 PHP 语言生...

  • 阿里云WEB直传php服务端

    阿里云服务端签名验证:YII2框架的 laravel框架的

  • Yii2 实例管理

    Yii2 实例管理 Yii2框架没有提供类似ZendFramework3中提供的ServiceManager.那么...

网友评论

    本文标题:Yii2框架源码研究3-ServiceLocator

    本文链接:https://www.haomeiwen.com/subject/kfrwlttx.html