Yii2框架源碼研究3-ServiceLocator

ServiceLocator類繼承了Component類和Object類的所有特性溜畅,也就是說他現(xiàn)在擁有了屬性床估,時間和行為這三個武器荐捻。服務定位器是一種設計模式,使用它的目的就是解耦糠惫,使得服務請求方不需要直接對服務提供者進行操作,只需要告訴服務定位器我現(xiàn)在想要什么服務钉疫,服務定位器就能夠定位到能夠提供這個服務的組件硼讽。
  從直觀的角度理解,假如現(xiàn)在我想發(fā)送一個郵件牲阁,如果沒有采用服務定位器這樣的設計方法固阁,那我現(xiàn)在肯定需要在現(xiàn)在的代碼里面,將發(fā)送郵件的這個組件進行實例化城菊,然后進行發(fā)送郵件的操作备燃。但是有時候突然發(fā)現(xiàn)這個發(fā)送郵件的組件不好用,需要換一個凌唬,那就必須要修改我的代碼了并齐,這樣一來二去的就很煩人,因為對于客戶端來說客税,他只是僅僅想發(fā)送一個郵件况褪,提供服務的組件不好用了竟然還得需要讓他來修改代碼。
  服務定位器的出現(xiàn)打破了這個狀況更耻,我現(xiàn)在只要告訴服務定位器我想要發(fā)送一個郵件测垛,那么服務定位器就能提供我需要的組件,我拿過來直接用就可以了秧均,如果這個組件想換了食侮,只需要在服務定位器這里將發(fā)送郵件這個服務定位到其他的某一個發(fā)送郵件的組件就可以了,客戶端的代碼根本不需要改變目胡。
  現(xiàn)在就來分析一下服務定位器這個模式需要什么要素锯七。想來想去還真的好簡單,不就是一個數(shù)組就行了嘛誉己!key為組件名稱眉尸,value為提供組件的類。接下來就看看在Yii框架中這個類是怎么實現(xiàn)的吧巫延!

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函數(shù)用來實現(xiàn)components屬性地消,也就是說炉峰,ServiceLocator的配置數(shù)組里面有一個key為components,并且這個key也對應了一個數(shù)組脉执,數(shù)組的每一項是key=>value類型的疼阔,key為組件名稱,value包含了提供組件的類。
  ServiceLocator中有兩個數(shù)組來存儲組件婆廊,一個是$_definitions迅细,用于直接存儲配置數(shù)組里面的內容,里面有可能僅僅存儲了提供組件的類的名稱淘邻。一個是$_components茵典,里面是提供組件的類的實例。
  兩個函數(shù)get()和set()就是用來獲取服務和設置服務的宾舅,設置服務的時候一開始并沒有將提供服務的類實例化统阿,只有當獲取到某一個服務的時候,如果提供這個服務的類沒有被實例化筹我,他才會被實例化扶平,get()函數(shù)會返回這個對象。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末蔬蕊,一起剝皮案震驚了整個濱河市结澄,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌岸夯,老刑警劉巖麻献,帶你破解...
    沈念sama閱讀 206,311評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異猜扮,居然都是意外死亡赎瑰,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評論 2 382
  • 文/潘曉璐 我一進店門破镰,熙熙樓的掌柜王于貴愁眉苦臉地迎上來餐曼,“玉大人,你說我怎么就攤上這事鲜漩≡雌” “怎么了?”我有些...
    開封第一講書人閱讀 152,671評論 0 342
  • 文/不壞的土叔 我叫張陵孕似,是天一觀的道長踩娘。 經(jīng)常有香客問我,道長喉祭,這世上最難降的妖魔是什么养渴? 我笑而不...
    開封第一講書人閱讀 55,252評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮泛烙,結果婚禮上理卑,老公的妹妹穿的比我還像新娘。我一直安慰自己蔽氨,他們只是感情好藐唠,可當我...
    茶點故事閱讀 64,253評論 5 371
  • 文/花漫 我一把揭開白布帆疟。 她就那樣靜靜地躺著,像睡著了一般宇立。 火紅的嫁衣襯著肌膚如雪踪宠。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,031評論 1 285
  • 那天妈嘹,我揣著相機與錄音柳琢,去河邊找鬼。 笑死润脸,一個胖子當著我的面吹牛染厅,可吹牛的內容都是我干的。 我是一名探鬼主播津函,決...
    沈念sama閱讀 38,340評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼肖粮,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了尔苦?” 一聲冷哼從身側響起涩馆,我...
    開封第一講書人閱讀 36,973評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎允坚,沒想到半個月后魂那,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,466評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡稠项,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 35,937評論 2 323
  • 正文 我和宋清朗相戀三年涯雅,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片展运。...
    茶點故事閱讀 38,039評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡活逆,死狀恐怖,靈堂內的尸體忽然破棺而出拗胜,到底是詐尸還是另有隱情蔗候,我是刑警寧澤,帶...
    沈念sama閱讀 33,701評論 4 323
  • 正文 年R本政府宣布埂软,位于F島的核電站锈遥,受9級特大地震影響,放射性物質發(fā)生泄漏勘畔。R本人自食惡果不足惜所灸,卻給世界環(huán)境...
    茶點故事閱讀 39,254評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望炫七。 院中可真熱鬧爬立,春花似錦、人聲如沸诉字。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,259評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽壤圃。三九已至陵霉,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間伍绳,已是汗流浹背踊挠。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留冲杀,地道東北人效床。 一個月前我還...
    沈念sama閱讀 45,497評論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像权谁,于是被迫代替她去往敵國和親剩檀。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,786評論 2 345

推薦閱讀更多精彩內容

  • Spring Cloud為開發(fā)人員提供了快速構建分布式系統(tǒng)中一些常見模式的工具(例如配置管理旺芽,服務發(fā)現(xiàn)沪猴,斷路器,智...
    卡卡羅2017閱讀 134,599評論 18 139
  • 1. Java基礎部分 基礎部分的順序:基本語法采章,類相關的語法运嗜,內部類的語法,繼承相關的語法悯舟,異常的語法担租,線程的語...
    子非魚_t_閱讀 31,581評論 18 399
  • Spring Boot 參考指南 介紹 轉載自:https://www.gitbook.com/book/qbgb...
    毛宇鵬閱讀 46,748評論 6 342
  • ¥開啟¥ 【iAPP實現(xiàn)進入界面執(zhí)行逐一顯】 〖2017-08-25 15:22:14〗 《//首先開一個線程,因...
    小菜c閱讀 6,358評論 0 17