工厂方法模式与IoC/DI
工廠方法模式與IoC/DI
?IoC——Inversion of Control? 控制反轉(zhuǎn)
?DI——Dependency Injection?? 依賴注入
1:如何理解IoC/DI
??????? 要想理解上面兩個概念,就必須搞清楚如下的問題:
- 參與者都有誰?
- 依賴:誰依賴于誰?為什么需要依賴??
- 注入:誰注入于誰?到底注入什么?
- 控制反轉(zhuǎn):誰控制誰?控制什么?為何叫反轉(zhuǎn)(有反轉(zhuǎn)就應(yīng)該有正轉(zhuǎn)了)?
- 依賴注入和控制反轉(zhuǎn)是同一概念嗎?
??????? 下面就來簡要的回答一下上述問題,把這些問題搞明白了,IoC/DI也就明白了。
(1)參與者都有誰:
??????? 一般有三方參與者,一個是某個對象;一個是IoC/DI的容器;另一個是某個對象的外部資源。
??????? 又要名詞解釋一下,某個對象指的就是任意的、普通的Java對象; IoC/DI的容器簡單點(diǎn)說就是指用來實現(xiàn)IoC/DI功能的一個框架程序;對象的外部資源指的就是對象需要的,但是是從對象外部獲取的,都統(tǒng)稱資源,比如:對象需要的其它對象、或者是對象需要的文件資源等等。
(2)誰依賴于誰:
????????當(dāng)然是某個對象依賴于IoC/DI的容器
(3)為什么需要依賴:
????????對象需要IoC/DI的容器來提供對象需要的外部資源
(4)誰注入于誰:
????????很明顯是IoC/DI的容器 注入 某個對象
(5)到底注入什么:
????????就是注入某個對象所需要的外部資源
(6)誰控制誰:
????????當(dāng)然是IoC/DI的容器來控制對象了
(7)控制什么:
????????主要是控制對象實例的創(chuàng)建
(8)為何叫反轉(zhuǎn):
??????? 反轉(zhuǎn)是相對于正向而言的,那么什么算是正向的呢?考慮一下常規(guī)情況下的應(yīng)用程序,如果要在A里面使用C,你會怎么做呢?當(dāng)然是直接去創(chuàng)建C的對象,也就是說,是在A類中主動去獲取所需要的外部資源C,這種情況被稱為正向的。那么什么是反向呢?就是A類不再主動去獲取C,而是被動等待,等待IoC/DI的容器獲取一個C的實例,然后反向的注入到A類中。
??????? 用圖例來說明一下,先看沒有IoC/DI的時候,常規(guī)的A類使用C類的示意圖,如圖7所示:
????????????????????????????????????? 圖7? 常規(guī)A使用C示意圖
當(dāng)有了IoC/DI的容器后,A類不再主動去創(chuàng)建C了,如圖8所示:
???????????????????????????????????? 圖8? A類不再主動創(chuàng)建C
而是被動等待,等待IoC/DI的容器獲取一個C的實例,然后反向的注入到A類中,如圖9所示:
???????????????????????????????????????????????圖9? 有IoC/DI容器后程序結(jié)構(gòu)示意圖
(9)依賴注入和控制反轉(zhuǎn)是同一概念嗎?
??????? 根據(jù)上面的講述,應(yīng)該能看出來,依賴注入和控制反轉(zhuǎn)是對同一件事情的不同描述,從某個方面講,就是它們描述的角度不同。依賴注入是從應(yīng)用程序的角度在描述,可以把依賴注入描述完整點(diǎn):應(yīng)用程序依賴容器創(chuàng)建并注入它所需要的外部資源;而控制反轉(zhuǎn)是從容器的角度在描述,描述完整點(diǎn):容器控制應(yīng)用程序,由容器反向的向應(yīng)用程序注入應(yīng)用程序所需要的外部資源。
(10)小結(jié)一下:
??????? 其實IoC/DI對編程帶來的最大改變不是從代碼上,而是從思想上,發(fā)生了“主從換位”的變化。應(yīng)用程序原本是老大,要獲取什么資源都是主動出擊,但是在IoC/DI思想中,應(yīng)用程序就變成被動的了,被動的等待IoC/DI容器來創(chuàng)建并注入它所需要的資源了。
??????? 這么小小的一個改變其實是編程思想的一個大進(jìn)步,這樣就有效的分離了對象和它所需要的外部資源,使得它們松散耦合,有利于功能復(fù)用,更重要的是使得程序的整個體系結(jié)構(gòu)變得非常靈活。
2:工廠方法模式和IoC/DI有什么關(guān)系呢?
??????? 從某個角度講,它們的思想很類似。
??????? 上面講了,有了IoC/DI過后,應(yīng)用程序就不再主動了,而是被動等待由容器來注入資源,那么在編寫代碼的時候,一旦要用到外部資源,就會開一個窗口,讓容器能注入進(jìn)來,也就是提供給容器使用的注入的途徑,當(dāng)然這不是我們的重點(diǎn),就不去細(xì)細(xì)講了,用setter注入來示例一下,看看使用IoC/DI的代碼是什么樣子,示例代碼如下:?
| public class A { ??? /** ??? ?* 等待被注入進(jìn)來 ??? ?*/ ??? private C c = null; ??? /** ??? ?* 注入資源C的方法 ??? ?* @param c 被注入的資源 ??? ?*/ ??? public void setC(C c){ ?????? this.c = c; ??? } ??? public void t1(){ ?????? //這里需要使用C,可是又不讓主動去創(chuàng)建C了,怎么辦? ?????? //反正就要求從外部注入,這樣更省心, ?????? //自己不用管怎么獲取C,直接使用就好了 ???????c.tc(); ??? } } |
接口C的示例代碼如下:?
| public interface C { ??? public void tc(); } |
?
??????? 從上面的示例代碼可以看出,現(xiàn)在在A里面寫代碼的時候,凡是碰到了需要外部資源,那么就提供注入的途徑,要求從外部注入,自己只管使用這些對象。
??????? 再來看看工廠方法模式,如何實現(xiàn)上面同樣的功能,為了區(qū)分,分別取名為A1和C1。這個時候在A1里面要使用C1對象,也不是由A1主動去獲取C1對象,而是創(chuàng)建一個工廠方法,就類似于一個注入的途徑;然后由子類,假設(shè)叫A2吧,由A2來獲取C1對象,在調(diào)用的時候,替換掉A1的相應(yīng)方法,相當(dāng)于反向注入回到A1里面,示例代碼如下:?
| public abstract class A1 { ??? /** ??? ?* 工廠方法,創(chuàng)建C1,類似于從子類注入進(jìn)來的途徑 ??? ?* @return C1的對象實例 ??? ?*/ ??? protected abstract C1 createC1(); ??? public void t1(){ ???????//這里需要使用C1類,可是不知道究竟是用哪一個 ???????//也就不主動去創(chuàng)建C1了,怎么辦? ?????? //反正會在子類里面實現(xiàn),這里不用管怎么獲取C1,直接使用就好了 ?????? createC1().tc(); ??? } } |
子類的示例代碼如下:?
| public class A2 extends A1 { ??? protected C1 createC1() { ?????? //真正的選擇具體實現(xiàn),并創(chuàng)建對象 ?????? return new C2(); ??? } } |
???????? C1接口和前面C接口是一樣的,C2這個實現(xiàn)類也是空的,只是演示一下,因此就不去展示它們的代碼了。
??????? 仔細(xì)體會上面的示例,對比它們的實現(xiàn),尤其是從思想層面上,會發(fā)現(xiàn)工廠方法模式和IoC/DI的思想是相似的,都是“主動變被動”,進(jìn)行了“主從換位”,從而獲得了更靈活的程序結(jié)構(gòu)。
總結(jié)
以上是生活随笔為你收集整理的工厂方法模式与IoC/DI的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 简单工厂模式,抽象工厂模式,反射工厂模式
- 下一篇: 控制反转(IoC) ? 工厂模式?