這篇文章主要介紹“l(fā)aravel服務(wù)容器的IoC模式是什么”,在日常操作中,相信很多人在laravel服務(wù)容器的IoC模式是什么問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”laravel服務(wù)容器的IoC模式是什么”的疑惑有所幫助!接下來,請跟著小編一起來學(xué)習(xí)吧!
網(wǎng)頁設(shè)計是網(wǎng)站建設(shè)的前奏,好的網(wǎng)頁設(shè)計更深度的剖析產(chǎn)品和設(shè)計風(fēng)格定位,結(jié)合最新的網(wǎng)頁設(shè)計流行趨勢,與WVI應(yīng)用標(biāo)準(zhǔn),設(shè)計出具企業(yè)表現(xiàn)力,大器而深穩(wěn)的網(wǎng)站界面設(shè)。成都創(chuàng)新互聯(lián)公司于2013年開始,是成都網(wǎng)站建設(shè)公司:提供企業(yè)網(wǎng)站設(shè)計,高端網(wǎng)站設(shè)計,營銷型企業(yè)網(wǎng)站建設(shè)方案,成都響應(yīng)式網(wǎng)站建設(shè)公司,小程序設(shè)計,專業(yè)建站公司做網(wǎng)站。
1、依賴
IoC模式主要是用來解決系統(tǒng)組件之間相互依賴關(guān)系的一種模式。那么什么是依賴呢?下面給出依賴的實例
trafficTool = new Foot(); } public function go_to_school() { $this->trafficTool->go(); } } $student = new Student(); $student->go_to_school();
這里要實現(xiàn)的功能是學(xué)生去學(xué)校,當(dāng)創(chuàng)建了一個學(xué)生實例的時候,同時也創(chuàng)建了一個交通工具的實例??梢钥吹綄W(xué)生和交通工具之間不可避免的產(chǎn)生了一個依賴。在程序中依賴可以理解為一個對象實現(xiàn)某個功能時需要其他對象相關(guān)功能的支持。
當(dāng)然交通工具還有很多,接著完善代碼
trafficTool = new Foot(); //$this->trafficTool = new Car(); //$this->trafficTool = new Bicycle(); /* * * * * * more and more * * * * */ } public function go_to_school() { $this->trafficTool->go(); } } $student = new Student(); $student->go_to_school();
是不是很恐怖!當(dāng)用new關(guān)鍵字在一個組件內(nèi)部實例化一個對象時就解決了一個依賴,但同時也引入了另一個嚴(yán)重的問題——耦合。在簡單情況下可能看不出耦合有多大問題,但是如果需求改變,如需要實例化的交通工具是自行車、汽車甚至是在設(shè)計中還不太清楚的工具時,就需要改變實例化的對象,如果又有很多地方用到了這段代碼,而這個程序又不是你寫的,這時你面對的將是噩夢。所以,這里我們不應(yīng)該在學(xué)生內(nèi)部固化’交通工具‘的初始化行為,而轉(zhuǎn)由外部負責(zé)
2、簡單工廠模式
原理:由一個工廠類根據(jù)傳入的參數(shù)(一般是字符串參數(shù)),動態(tài)決定應(yīng)該創(chuàng)建哪一個產(chǎn)品子類(這 些產(chǎn)品子類繼承自同一個父類或接口)的實例,并以父類形式返回。
適用情況:所有的產(chǎn)品子類都有同一個父類(或接口),屬于同一個產(chǎn)品系列 產(chǎn)品子類比較少的、創(chuàng)建操作比較簡單 。
在前面的實例中我們知道,交通工具的實例化過程是經(jīng)常需要改變的,所以我們將這部分提取到外部來管理,這也就體現(xiàn)了面向?qū)ο笤O(shè)計的一個原則,及找出程序中會變化的方面然后將其和固定不變的方面相分離。一種簡單的實現(xiàn)方案是利用工廠模式,這里我們用簡單工廠模式實現(xiàn)。實例如下:
class TrafficToolFactory { public function createTrafficTool($name) { switch ($name){ case 'Foot': return new Foot(); break; case 'Car': return new Car(); break; case 'Bicycle': return new Bicycle(); break; default: exit('set trafficTool error!'); break; } } } class Student { private $trafficTool; public function __construct($trafficTool) { //通過工廠產(chǎn)生依賴的交通工具實例 $factory = new TrafficToolFactory(); $this->trafficTool = $factory->createTrafficTool($trafficTool); } public function go_to_school(){ $this->trafficTool->go(); } } $student = new Student('Car'); //$student2 = new Student('Foot'); //$student3 = new Student('Bicycle'); $student->go_to_school();
這里我們添加了“交通工具”工廠,在學(xué)生實例化的過程中指定需要的交通工具,則工廠生產(chǎn)相應(yīng)的交通工具實例。在一些簡單的情況下,簡單工廠模式可以解決這個問題。我們看到學(xué)生和交通工具之間的依賴關(guān)系沒有了,但是卻變成學(xué)生和交通工具工廠之間的依賴。當(dāng)需求增加時,我們需要修改簡單工廠,如果依賴增多,工廠將十分龐大,依然不利于維護。下一步就是我們今天的主要配角 —— DI
3、DI(Dependency Injection 依賴注入)
本文中提到的一系列依賴,只要不是由內(nèi)部產(chǎn)生(比如初始化、構(gòu)造函數(shù) __construct 中通過工廠方法、自行手動 new 的),而是由外部以參數(shù)或其他形式注入的,都屬于依賴注入(DependencyInjection簡稱DI) 。實例如下:
class Student { private $trafficTool; public function __construct(Go_To_School $trafficTool) { $this->trafficTool = $trafficTool; } public function go_to_school(){ $this->trafficTool->go(); } } $car = new Car(); $student = new Student($car); $student->go_to_school();
現(xiàn)在初始化學(xué)生類時提供的參數(shù)必須是Go_To_School接口類的一個實例,即通過依賴注入的方式解決依賴問題,否則就會提示出錯。這里要注意,依賴注入要以接口的形式進行限制,不能隨意開放
4、IoC容器(Inversion of Control 控制反轉(zhuǎn))
IoC是將設(shè)計好的類交給系統(tǒng)去控制,而不是在類內(nèi)部控制。這稱為控制反轉(zhuǎn)。上例中我們是通過手動注入依賴,而IoC容器實現(xiàn)了依賴的自動注入。下面給出一個簡化版的例子。里面涉及到反射機制,網(wǎng)上有很多關(guān)于反射機制的講解,讀者可以自行查找,這里就不細說了。
class Container { //用于裝提供實例的回調(diào)函數(shù),真正的容器還會裝實例等其他內(nèi)容 //從而實現(xiàn)單例等高級功能 protected $bindings = []; //綁定接口和生成相應(yīng)實例的回調(diào)函數(shù) public function bind($abstract, $concrete=null, $shared=false) { //如果提供的參數(shù)不是回調(diào)函數(shù),則產(chǎn)生默認的回調(diào)函數(shù) if(!$concrete instanceof Closure) { $concrete = $this->getClosure($abstract, $concrete); } $this->bindings[$abstract] = compact('concrete', 'shared'); } //默認生成實例的回調(diào)函數(shù) protected function getClosure($abstract, $concrete) { return function($container) use ($abstract, $concrete) { $method = ($abstract == $concrete) ? 'build' : 'make'; return $container->$method($concrete); }; } //解決接口和要實例化類之間的依賴關(guān)系 public function make($abstract) { $concrete = $this->getConcrete($abstract); if($this->isBuildable($concrete, $abstract)) { $object = $this->build($concrete); } else { $object = $this->make($concrete); } return $object; } protected function isBuildable($concrete, $abstract) { return $concrete === $abstract || $concrete instanceof Closure; } //獲取綁定的回調(diào)函數(shù) protected function getConcrete($abstract) { if(!isset($this->bindings[$abstract])) { return $abstract; } return $this->bindings[$abstract]['concrete']; } //實例化對象 public function build($concrete) { if($concrete instanceof Closure) { return $concrete($this); } $reflector = new ReflectionClass($concrete); if(!$reflector->isInstantiable()) { echo $message = "Target [$concrete] is not instantiable"; } $constructor = $reflector->getConstructor(); if(is_null($constructor)) { return new $concrete; } $dependencies = $constructor->getParameters(); $instances = $this->getDependencies($dependencies); return $reflector->newInstanceArgs($instances); } //解決通過反射機制實例化對象時的依賴 protected function getDependencies($parameters) { $dependencies = []; foreach($parameters as $parameter) { $dependency = $parameter->getClass(); if(is_null($dependency)) { $dependencies[] = NULL; } else { $dependencies[] = $this->resolveClass($parameter); } } return (array)$dependencies; } protected function resolveClass(ReflectionParameter $parameter) { return $this->make($parameter->getClass()->name); } }
這就是簡化版的IoC容器類,使用bind()函數(shù)進行服務(wù)綁定,使用make()函數(shù)來進行解析,最后在容器內(nèi)由build()函數(shù)創(chuàng)建并返回實例。下面是具體如何使用
//實例化IOC容器 $ioc = new Container(); //填充容器 $ioc->bind('Go_To_School', 'Car'); //第一個參數(shù)'Go_To_School'是接口,第二個參數(shù)'Car'是交通工具類 $ioc->bind('student', 'Student'); //第一個參數(shù)'student'可以理解為服務(wù)別名,用make()實例化的時候直接使用別名即可,第二個參數(shù)'Student'是學(xué)生類 //通過容器實現(xiàn)依賴注入,完成類的實例化 $student = $ioc->make('student'); $student->go_to_school();
填充容器的時候也可以直接綁定自定義的回調(diào)函數(shù):
$ioc->bind('Go_To_School', function (){ return new Car(); });
現(xiàn)在,我們不僅解除了學(xué)生類與交通工具類的依賴關(guān)系,而且容器類沒有和他們產(chǎn)生任何依賴。我們通過注冊、綁定(bind)的方式向容器中添加一段可以被執(zhí)行的回調(diào)(可以是匿名函數(shù)、非匿名函數(shù)、類的方法)作為創(chuàng)建一個類的實例的方法,只有在真正的創(chuàng)建(make)操作被調(diào)用執(zhí)行時,才會觸發(fā)。這樣一種方式,使得我們更容易在創(chuàng)建一個實例的同時解決其依賴關(guān)系,并且更加靈活。當(dāng)有新的需求,只需另外綁定一個回調(diào)即可。例如現(xiàn)在我們想步行去學(xué)校,只要再綁定$ioc->bind('Go_To_School', 'Foot');就可以了。用何種方式去學(xué)校,我們可以自由的選擇。
通過上述例子可以看到IOC容器最核心的功能,解決依賴注入的根本問題。在實現(xiàn)過程中,沒有用new關(guān)鍵字來實例化對象,不需要人來關(guān)注組件之間的依賴關(guān)系,只要在容器填充過程中理順接口和實現(xiàn)類之間的關(guān)系及實現(xiàn)類與依賴接口之間的關(guān)系就可以流水線式的完成實現(xiàn)類的實例化過程。
到此,關(guān)于“l(fā)aravel服務(wù)容器的IoC模式是什么”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識,請繼續(xù)關(guān)注創(chuàng)新互聯(lián)網(wǎng)站,小編會繼續(xù)努力為大家?guī)砀鄬嵱玫奈恼拢?/p>
文章題目:laravel服務(wù)容器的IoC模式是什么
網(wǎng)頁路徑:http://weahome.cn/article/pcgoph.html